初始化项目
mkdir webpack-config-demo
yarn init -y
yarn add webpack webpack-cli
复制代码
package.json中添加
"scripts": {
"build": "webpack"
},
复制代码
+ src/index.js
const fn = ()=>{
var a = 100
var b = 100
setTimeout(()=>{
console.log(a + b)
})
}
fn()
复制代码
运行yarn build
,就会看见当前打包好的dist.js
文件
webpack build 支持IE
+ browserslistrc文件
[production]
> 1%
ie 9
[modern]
last 1 chrome version
last 1 firefox version
[ssr]
node 12
复制代码
用babel-loader打包js
yarn add -D babel-loader @babel/core @babel/preset-env
``
```js
+ webpack.config.js
module.exports = {
mode: "production",
module: {
rules: [
{
test: /\.jsx?$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env'],
['@babel/preset-react',
{
runtime: 'classic' //使用经典版
}
]
]
}
}
}
]
}
}
复制代码
用babel-laoder打包jsx
yarn add @babel/preset-react
复制代码
use: {
loader: 'babel-loader',
options: {
presets: [
'@babel/preset-env',
'@babel/preset-react' //新增
]
}
}
复制代码
测试
src/index.js
import JsxDemo from'./jsx-demo.jsx'
console.log(JsxDemo)
复制代码
+ src/jsx-demo.jsx
const JsxDemo = () => {
return (
<div>jsx-demo</div>
)
}
export default JsxDemo
复制代码
yarn build
给webpack配置eslint
eslint-config-react-app 此包包含Create React App使用的可共享 ESLint 配置。npm link
yarn add -D
eslint-config-react-app
@typescript-eslint/eslint-plugin@^4.0.0
@typescript-eslint/parser@^4.0.0
babel-eslint@^10.0.0
eslint@^7.5.0
eslint-plugin-flowtype@^5.2.0
eslint-plugin-import@^2.22.0
eslint-plugin-jsx-a11y@^6.3.1
eslint-plugin-react@^7.20.3
eslint-plugin-react-hooks@^4.0.8
复制代码
+ .eslintrc.js
module.exports = {
//继承 eslint-config-react-app这个里面包含create react app的eslint配置
"extends": "react-app",
rules: {
// jsx使用 react
'react/jsx-uses-react': [2],
// 提示要在 JSX 文件里手动引入 React
'react/react-in-jsx-scope': [2],
'no-console': [0]
},
}
复制代码
让webpack
可以感知到eslint
的配置,从而在编译的过程中提示报错信息
yarn add eslint-webpack-plugin -D
复制代码
webpack/config.js
const ESLintPlugin = require('eslint-webpack-plugin');
module.exports = {
// ...
plugins: [new ESLintPlugin({
extensions: ['.js', '.jsx'] //不加就不会去检测.jsx文件了
})],
// ...
};
复制代码
在没加eslint-webpack-plugin
之前虽然我们发现在编辑器中eslint
给我们报错了,但是在我们运行yarn build
的时候他还是可以编译成功的。如下图
下面我们来看看加完之后的情况,这个时候,不仅eslint
报错了webpack
构建的时候也会在控制台报错,这样就很好地使用了eslint
。
用babel-loader打包TypeScript
yarn add @babel/preset-typescript -D
复制代码
webpack.config.js
test: /\.[tj]sx?$/,
presets: [['@babel/preset-typescript']]
复制代码
添加一个test.tsx
,并且在index.js
中引入,以下结果编译成功。
让eslint支持TypeScript
让eslint
支持ts
,添加相关的配置。
yarn add eslint-config-airbnb-typescript @types/react -D
复制代码
.eslintrc.js
//覆盖之前的配置(检测ts代码)
overrides: [{
files: ['*.ts', '*.tsx'],
parserOptions: {
project: './tsconfig.json',
},
extends: ['airbnb-typescript'],
rules: {
'@typescript-eslint/object-curly-spacing': [0],
'import/prefer-default-export': [0],
'no-console': [0],
'import/extensions': [0]
}
}]
复制代码
我们运行yarn build
发现此时编译还是可以成功的。
webpack.config.js 添加'.ts' '.tsx'
plugins: [new ESLintPlugin({
extensions: ['.js', '.jsx', '.ts', '.tsx'] //不加就不会去检测.jsx文件了
})],
复制代码
修改之后的效果
用babel-loader打包tsx
生成tsconfig.json
文件。
npx tsc --init
复制代码
{
"jsx": "react", // Specify JS
"strict": false, // 关闭严格模式
"noImplicitAny": true, //没有隐式的any
}
复制代码
同样我们编写tsx-demo.tsx
文件在index.js
中引入进行测试。
CRLF 是什么?
一、LF和CRLF是什么
- CRLF 是 carriage return line feed 的缩写,中文意思是回车换行。
- LF 是 line feed 的缩写,中文意思也是换行。
- 它们都是文本换行的方式。
二、LF和CRLF区别
CRLF
: “\r\n”, windows系统环境下的换行方式LF
: “\n”, Linux系统环境下的换行方式
让js和ts支持@alias
js 支持
webpack.config.js
const path = require('path')
resolve: {
alias: {
'@': path.join(__dirname, './src/')
}
},
复制代码
ts 支持
tsconfig.json 添加
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": [
"src/*"
]
},
}
复制代码
引入代码测试
让webpack支持scss
yarn add sass-loader sass style-loader css-loader -D
复制代码
module.exports = {
module: {
rules: [
{
test: /\.s[ac]ss$/i,
//执行顺序从右到左
use: [
// Creates `style` nodes from JS strings
"style-loader",
// Translates CSS into CommonJS
"css-loader",
// Compiles Sass to CSS
"sass-loader",
],
},
],
},
};
复制代码
- sass-loader npm点进去里面有具体的配置。
- Vue-loader这个是
Vue-loader
的官方文档
scss自动import全局文件
{
test: /\.s[ac]ss$/i,
use: [
// Creates `style` nodes from JS strings
"style-loader",
// Translates CSS into CommonJS
"css-loader",
// Compiles Sass to CSS
{
loader: "sass-loader",
options: {
//需要添加的字符串
additionalData: `
@import '@/var.scss';
`,
sassOptions: {
includePaths: [__dirname] //基于当前目录
},
},
},
],
},
复制代码
scss分享变量给js
可以让项目中用到的css
变量用同一份js
和scss
共同维护一份变量。
+ scss-export.scss
:export {
border-color: $body-color;
}
复制代码
index.js
import vars from './scss-export.scss';
console.log(vars)
复制代码
webpack支持less文件
yarn add less less-loader -D
复制代码
@import './_var.less';
body{
color: @color;
}
复制代码
webpack.config.js
{
test: /\.less$/i,
use: [
{
loader: "style-loader",
},
{
loader: "css-loader",
options: {
modules: {
compileType: 'icss',
},
},
},
{
loader: "less-loader",
options: {
additionalData: `
@import './_var.less';
`
},
},
],
},
复制代码
less分享给js
_var.less
@color: pink;
:export{
color: @color;
}
复制代码
index.js
import vars from './_var.less';
console.log(vars)
复制代码
对比scss 和less
要选的话就选scss
stylus文件
style.stylus
color = black;
//变量分享给js
:export{
color: color
}
复制代码
yarn add stylus stylus-loader -D
复制代码
webpack.config.js
{
test: /\.styl$/,
use: [
{
loader: "style-loader",
},
{
loader: "css-loader",
options: {
modules: {
compileType: 'icss',
},
}
},
{
loader: "stylus-loader",
options: {
stylusOptions: {
import: [path.resolve(__dirname, "src/_var.styl")]
}
}
}
]
}
复制代码
webpack config 重构
webpack.config.js
const cssLoaders = (...loaders) => [
// Creates `style` nodes from JS strings
"style-loader",
// Translates CSS into CommonJS
{
loader: 'css-loader',
options: {
modules: {
compileType: 'icss',
},
},
},
...loaders
]
复制代码
生产页面单独提取css文件
mini-css-extract-plugin webpack文档
yarn add mini-css-extract-plugin -D
复制代码
webpack.config.js
const cssLoaders = (...loaders) => [
// Creates `style` nodes from JS strings
mode === 'production' ? MiniCssExtractPlugin.loader : "style-loader",
// Translates CSS into CommonJS
{
loader: 'css-loader',
options: {
modules: {
compileType: 'icss',
},
},
},
...loaders
]
plugins: [
new ESLintPlugin({
extensions: ['.js', '.jsx', '.ts', '.tsx'] //不加就不会去检测.jsx文件了
}),
mode === 'production' && new MiniCssExtractPlugin({
filename: '[name].[contenthash].css'
}),
].filter(Boolean)
复制代码
自动生成HTML页面
yarn add html-webpack-plugin -D
复制代码
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: 'index.js',
output: {
filename: '[name].[contenthash].js'
},
plugins: [
new HtmlWebpackPlugin()
]
}
复制代码
webpack优化 单独打包runtime
optimization: {
runtimeChunk: 'single', //运行时文件单独打包
},
复制代码
为什么要单独打包runtime
runtime
里面的文件是webpack
为了运行main.js
文件所要依赖的文件。- 如果不单独打包,如果我们修改了
webpack
的配置之后mian.js
里面的内容就会发生变化,用户的缓存就会失效,如果单独打包的话当修改完webpack
的配置之后只,如果我们没有改变main.js
里面的内容的话,就不会重新打包main.js
的内容,这样就可以节省宽带,提高用户访问页面的速度。
webpack优化 用splitChunks将node依赖单独打包
在编译的时候要缓存React
等类库文件。
webpack优化 固定modules
webpack.config.js
optimization: {
moduleIds: 'deterministic',
runtimeChunk: 'single', //运行时文件单独打包
splitChunks: {
cacheGroups: {
vendor: {
priority: 10,
minSize: 0, /* 如果不写 0,由于 React 文件尺寸太小,会直接跳过 */
test: /[\\/]node_modules[\\/]/, // 为了匹配 /node_modules/ 或 \node_modules\
name: 'vendors', // 文件名
chunks: 'all', // all 表示同步加载和异步加载,async 表示异步加载,initial 表示同步加载
// 这三行的整体意思就是把两种加载方式的来自 node_modules 目录的文件打包为 vendors.xxx.js
// 其中 vendors 是第三方的意思
}
},
},
},
复制代码
之后再运行yarn build
可以看见引入了三个js
文件
webpack 多页面
webpack.config.js
entry: {
main: './src/index.js',
admin: './src/admin.js'
},
plugins: [
new HtmlWebpackPlugin({
filename: 'index.html',
chunks: ['main']
}),
new HtmlWebpackPlugin({
filename: 'admin.html',
chunks: ['admin']
})
]
复制代码
webpack优化 common插件
如果共有的文件就打包成一个文件,如果两个入口都同时引用了一个文件,
optimization: {
runtimeChunk: 'single', //运行时文件单独打包
splitChunks: {
cacheGroups: {
common: {
priority: 5,
minSize: 0,
minChunks: 2, //同一个文件至少被多少个入口引用了
chunks: 'all',
name: 'common'
}
},
},
},
复制代码
runtime
为了运行mian.js
所要提供的代码。node_modules
venders 全局的common
模块间的 admin.js 和 index.jsself
自身的
看这个打包之后页面引入js
的顺序
无限多页面的实现思路
webpack.config.js
let entry = {}
let outputHtml = []
var pages = fs.readdirSync(path.resolve(__dirname, pagesDir))
pages.forEach((item)=>{
let name = item.replace('.js', '')
entry[name] = `${pagesDir}${item}`
outputHtml.push(new HtmlWebpackPlugin({
filename: `${name}.html`,
chunks: [name]
}))
})
复制代码
只需要把这两个参数弄成动态生成的即可满足要求。测试之后大功告成!!!
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END