Appearance
一 注意
1. webpack
版本问题
- 由于教程使用的是
webpack4
的版本,所以也建议使用webpack4
的版本,比较好兼容,尤其是更新到webpack5
以后,有很多兼容性的问题,例如html
打包插件不兼容,devServer
调用方式也有变化,css
单独打包的插件也会出现不兼容。
2. 特别注意
webpack5
使用html-webpack-plugin
时会报错The 'compilation' argument must be an instance of Compilation
,解决办法是把该插件的安装方法从npm i html-webpack-plugin -D
改为npm i html-webpack-plugin@next -D
3. webpack
5 个核心概念
entry
output
loader
plugins
mode
Loader 和 Plugin 的区别
- loader 是一个转换器,将 a 文件进行编译输出 b 文件,这里是操作文件。单纯的文件转换。
- plugin 是一个扩展器,它丰富了 webpack 本身,针对是 loader 结束后,webpack 打包的整个过程,它并不直接操作文件,而是基于事件机制工作,会监听 webpack 打包过程中的某些节点,执行任务
二 webpack
初体验
1. webpack
初体验
运行指令: 开发环境
webpack ./src/index.js -o ./build --mode=development
生产环境webpack ./src/index.js -o ./build --mode=production
结论:
webpack
只能处理js/json
文件,不能处理css/img
等其他资源 生产环境比开发环境多一个压缩js
代码
2. 打包样式资源
打包样式资源,需要使用 webpack.config.js
,是 webpack
的配置文件,在其中可以配置调用的loader
,plugins
, 并且需要在module
中配置rules
。
打包
css
资源使用style-loader
,css-loader
,使用之前需要使用npm
进行安装:npm i style-loader css-loader -D
,并在`webpack.config.js 中进行配置。打包
less
资源使用style-loader
,css-loader
,less-loader
,使用之前需要使用npm
进行安装:(其中less-loader
又需要依赖less
模块)npm i less less-loader -D
,并在`webpack.config.js 中进行配置。
特别的,在path
中需要使用绝对地址,nodejs
提供了接口,使用const { resolve } = require('path')
调用,随后在path
中调用 resolve(__dirname, "build")
webpack.config.js
配置
javascript
const { resolve } = require('path') // 用于定义当前文件的绝对路径
module.exports = {
entry: './src/index.js',
output: {
filename: 'built.js',
path: resolve(__dirname, 'build')
},
module: {
// loader的配置
rules: [
{
// test 用于匹配哪些文件
test: /\.css$/,
// 使用哪些loader 进行处理
use: [
// 创建style标签,再将js中的样式资源插入,添加到head中生效
'style-loader',
// 将css文件变成commonjs模块加载js中,内容样式是字符串
'css-loader'
// 注意:use调用的loader,顺序是从下往上/从右往左
]
},
{
test: /\.less$/,
use: ['style-loader', 'css-loader', 'less-loader']
}
]
},
plugins: [],
mode: 'development'
}
3. 打包html
资源
打包html
文件则需要使用html-webpack-plugin
的plugins
,但plugins
和loader
的使用有一些不同:loader
的使用需要经过 (1)下载->(2)使用,而plugins
的使用则是 (1)下载->(2)调用->(3)使用。
- 具体使用
html-webpack-plugin
:npm i html-webpack-plugin -D
进行安装。之后在webpack.config.js
中进行引用,const HtmlWebPackPlugin = require('html-webpack-plugin')
。
webpack.config.js
配置
javascript
const HtmlWebPackPlugin = require('html-webpack-plugin');// 调用html-webpack-plugin插件
module.exports = {
plugins: [
// plugins 的配置
// 打包html资源需要 html-webpack-plugin 的包。
// 功能:默认会创建一个空的html文件,引入打包输出的所有资源(包括js/css),但是此时的html文件。结构(包括 title 等没有自定义)
// 现在的需求:需要一个有结构的html文件,可以使用template定义一个文件
new HtmlWebPackPlugin({
// 意思是 复制 ./src/index.html 文件,并自动打包输出所有的资源文件(js/css)
template: './src/index.html'
})
],
mode: 'development'
4. 打包图片资源 url-loader file-loader
打包
css
中的图片资源使用url-loader
使用之前需要使用npm
进行安装:(其中url-loader
又需要依赖file-loader
模块)npm i url-loader file-loader -D
,并在`webpack.config.js 中进行配置。除了
css
中的图片需要打包,还有html
页面中的图片需要打包,html-loader
专门用于处理html
文件中的图片,主要是负责引入html
中的img
,从而能够被url-loader
进行处理。
webpack.config.js
配置
javascript
const { resolve } = require("path"); // 获取绝对地址
const HtmlWebPackPlugin = require("html-webpack-plugin");
module.exports = {
rules: [
{
test: /\.less$/,
// 需要使用多个loader,则使用use
use: ["style-loader", "css-loader", "less-loader"],
},
{
// 这种方式只能处理样式中的图片,不能处理html中的img图片
test: /\.(jpg|png|gif)$/,
// 如果只有一个loader,就直接使用loader
loader: "url-loader",
// url-loader 需要依赖file-loader 和url-loader
// url-loader 可以将较小的图片转换为base64位图片,减少服务器的请求
options: {
// limit中的8 指图片小于8K,就会被base64处理
// base64的优点:减少请求的数量
// 缺点:图片体积会增大
limit: 8 * 1024,
// [name]取文件原本的名字
// [hash:10]取图片的hash值的前10位
// [ext]取文件原来的扩展名
name: "[name].[hash:10].[ext]",
},
},
{
test: /\.html$/,
// html-loader 专门用于处理html文件中的图片
loader: "html-loader",
},
],
},
};
5. 打包其他资源
- 打包其他资源,就是除了样式、
js
,图片等的其他资源。使用file-loader
进行打包。在之前的处理图片资源中,已经使用npm
下载过。
webpack.config.js
配置
javascript
const { resolve } = require('path')
module.exports = {
module: {
rules: [
// 打包其他资源 可以使用test指定文件类型,也可以使用exclude排除
{
exclude: /\.(css|js|html)$/,
loader: 'file-loader',
options: {
name: '[name].[hash:10].[ext]',
outputPath: 'other' // 在outputPath 中配置其他资源的输出目录
}
}
]
}
}
6. devServer
开发服务器
devServer
是webpack
提供的一个本地服务器,用于自动化,包括编译,打包,打开浏览器,自动刷新浏览器。并且只会在内存中编译打包,不会有具体的输出。
使用
devServer
需要进行安装npm i webpack-dev-server -D
启动devServer
的指令为:webpack4
:npx webpack-dev-server
webpack5
:npx webpack serve
webpack.config.js
配置
javascript
const { resolve } = require('path')
module.exports = {
devServer: {
// 运行项目的目录
contentBase: resolve(__dirname, 'bulid'),
// 启动gzip压缩
compress: true,
// 端口号
port: 5050,
// 自动打开浏览器
open: true
}
}
然后使用npm run webpack serve
启动服务,另,也可以不对webpack.config.js
进行配置,直接启动webpack serve
服务。
7. 开发环境的搭建
开发环境就是包括之前的图片、html
、其他资源的打包配置,并调用devServer
,为了将打包的资源输出到对应目录,需要在options
中配置 outputPath
,但是入口文件只需在output
中配置filename
,另外css
类型的文件转换为js
文件,所以此时没有额外输出css
文件。
webpack.config.js
配置
javascript
const HtmlWebPackPlugin = require('html-webpack-plugin')
const { resolve } = require('path')
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/build.js', // 增加 js/build.js js会输出到js目录中
path: resolve(__dirname, 'build')
},
module: {
rules: [
// 处理css资源
{
test: /\.css$/,
use: ['style-loader', 'css-loader']
},
// 处理less资源
{
test: /\.less$/,
use: ['style-loader', 'css-loader', 'less-loader']
},
// 处理图片资源
{
test: /\.(jpg|png|gif|svg)$/,
loader: 'url-loader',
options: {
name: '[name].[hash:10].[ext]',
limit: 8 * 1024,
outputPath: 'imgs' // 在outputPath 中配置其他资源的输出目录
}
},
// 处理html中的图片资源
{
test: /\.html$/,
loader: 'html-loader'
},
// 处理其他资源
{
exclude: /\.(css|js|less|jpg|png|gif|html|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[hash:10].[ext]',
outputPath: 'other' // 在outputPath 中配置其他资源的输出目录
}
}
]
},
plugins: [
// 处理html资源
new HtmlWebPackPlugin({
template: './src/index.html'
})
],
mode: 'development',
devServer: {
contentBase: resolve(__dirname, 'bulid'),
compress: true,
port: 5050,
open: true
}
}
三 webpack
1. 提取 css
成为一个单独文件 mini-css-extract-plugin
打包时提取
css
成为一个单独文件,使用mini-css-extract-plugin
进行实现,webpack5
暂时还不兼容使用
npm i mini-css-extract-plugin -D
进行安装,然后再plugins
中配置:new MiniCssExtractPlugin({})
,以及loader
中的配置:MiniCssExtractPlugin.loader
webpack.config.js
配置
javascript
// 用于将css文件单独提取成一个文件的插件
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
module.exports = {
module: {
rules: [
{
test: /\.css$/,
use: [
// 'style-loader',
// 用MiniCssExtractPlugin.loader取代style-loader ,不用将css文件插入head中,而是引用一个单独的文件
MiniCssExtractPlugin.loader,
'css-loader'
]
}
]
},
plugins: [
// plugins 中进行配置
new MiniCssExtractPlugin({
// 对输出的css文件重命名
filename: 'css/[hash:5].css'
})
]
}
2. 处理 css
文件的兼容性 postcss
css
兼容性处理使用postcss
,需要安装两个loader
,分别是postcss-loader
和postcss-preset-env
。postcss
是帮助webpack
在package.json
中找到browserslist
中的配置,通过配置加载指定的css
兼容性。 下面是package.json
中的配置,其中的生产和开发环境不是指webpack.config.js
中配置的环境,是指nodejs
的环境,所以需要修改nodejs
的环境为开发环境。修改的方式为:process.env.NODE_ENV = 'development'
使用
npm
进行安装:npm i postcss-loader postcss-preset-env -D
,安装之后在loader
中进行配置,
javascript
{
loader: 'postcss-loader',
options: {
postcssOptions: {
ident: 'postcss',
plugins: [
require('postcss-preset-env')()
]
}
}
}
- 除了在
webpack.config.js
中进行配置以外,还需要在package.json
中进行borwerslist
的配置:
json
"borwerslist": {
// 开发环境
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
],
// 生产环境
"production": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
}
borwerslist
的配置不是固定的,可以有其他的参考,而且当中的生产和开发环境是指 nodejs 环境变量,默认是生产环境的,所以要调整 nodejs 的环境变量还要在webpack.config.js
中进行配置:process.env.NODE_ENV = 'development'
javascript
process.env.NODE_ENV = 'development'
3. 处理 css
文件的压缩
压缩
css
需要使用optimize-css-assets-webpack-plugin
插件。使用
npm i optimize-css-assets-webpack-plugin -D
进行安装,安装之后在webpack.config.js
中进行配置使用,和之前的插件一样:
javascript
const OptimizeCssAssetsWebpackPlugin = require("optimize-css-assets-webpack-plugin"); // 引用插件
...
plugins: [
new OptimizeCssAssetsWebpackPlugin()
];
...
4. js
的语法检查
js
的语法检查使用eslint
,依赖于eslint-loader
、eslint
,只检查自己写的源代码,第三方库不检查, 使用前还得设置检查规则, 需要在package.json
中进行配置。 通常使用Airbnb
的js
语法规范,或者是自己使用eslint
定义。
vscode
下载eslint
插件;npm i eslint -g
全局安装eslint
插件;- 在对应的文件夹建立项目
npm init
,和eslint
初始化eslint --init
- 配置
vscode
中eslint
的引用地址:
json
"eslint.options": {
"configFile": "E:/Git/studyProgram/.eslintrc.js"
},
- 配置
.eslintrc.js
具体配置:
javascript
module.exports = {
env: {
browser: true,
commonjs: true,
es6: true
},
extends: 'eslint:recommended',
parserOptions: {
sourceType: 'module'
},
rules: {
indent: [
'error',
2,
{
SwitchCase: 1
}
],
'linebreak-style': ['off', 'windows'],
// 引号
quotes: ['error', 'single', { avoidEscape: true }],
// 末尾的分号
semi: ['error', 'always'],
// 未定义的变量(例如其他页面调用的变量,在另外的页面中使用)
'no-undef': [0],
// 定义了却没有调用的变量
'no-unused-vars': [
0
// { 'vars': 'all', 'args': 'after-used', 'ignoreRestSiblings': false }
],
'no-prototype-builtins': 'error'
}
}
5. js
的兼容性
js
兼容性处理使用babel-loader
@babel/core
@babel/preset-env
进行简单的兼容性处理,只能转换基本的语法,不能转换Promise
等 使用npm i babel-loader @babel/core @babel/preset-env -D
进行安装,使用时,需要在webpack.config.js
中进行配置:
javascript
...
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options:{
presets:['@babel/presets-env']
}
}
...
- 使用
@babel/polyfill
可以进行全部的兼容性处理,但是转换之后的文件,体积太大,基本弃用了。npm i @babel/polyfill -D
安装之后,调用上述的loader
随后在需要全部兼容的js
文件中添加import '@babel/polyfill'
exclude
用于排除不需要打包的文件夹- 按需处理,根据需要进行浏览器的兼容性处理,需要使用
core-js
,npm i core-js -D
安装后,还需要修改webpack.config.js
的配置,注:presets
中,是两个方括号。
javascript
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
// 预设 指示babel做怎么样的兼容性处理
// presets: ['@babel/preset-env'] // 基础js兼容性处理
presets: [
[
'@babel/preset-env',
{
// 进行按需加载
useBuiltIns: 'usage',
// corejs 的版本
corejs: {
version: 3
},
// 兼容性目标
targets: {
chrome: '60',
ie: '9',
firefox: '60'
}
}
]
]
}
}
6. js
的压缩
- 使用
webpack
进行js
的压缩。只需要把webpack.config.js
中的模式调为生产模式,就能自动进行js
的压缩。mode: 'production'
7. html
的压缩
在
webpack@4.41.6
版本中,不会自动进行html
的压缩,但是在高版本的webpack
中则是会自动压缩html
文件的。 压缩html
文件使用的是html-webpack-plugin
,在new HtmlWebpackPlugin()
中进行一些配置就可以进行html
文件的压缩:javascript... new HtmlWebpackPlugin({ template: './index.html', minify:{ // 移除空格 collapseWhitespace:true, // 移除注释 removeComments:true } }), ...
8. 生产环境配置
- 生产环境的配置,就是包括
css
-js
-hmtl
- 图片 - 其他文件,环境变量为生产环境的打包配置,css
文件不止是css
文件,还有其它的如:less
scss
styls
等的处理,不过此处以less
文件为例。由于内容较多,配置的时候最好能够配置一项测试一项。避免后面不知道哪里有问题。
webpack.config.js
配置
javascript
const { resolve } = require('path')
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')
const HtmlWebPackPlugin = require('html-webpack-plugin')
// 复用loader
const commonCssLoader = [
MiniCssExtractPlugin.loader,
'css-loader',
{
loader: 'postcss-loader',
options: {
postcssOptions: {
ident: 'postcss',
plugins: [require('postcss-preset-env')()]
}
}
}
]
module.exports = {
entry: './src/js/index.js',
output: {
filename: 'js/index.js',
path: resolve(__dirname, 'build')
},
module: {
rules: [
// css 处理
{
test: /\.css$/,
use: [...commonCssLoader]
},
// less 文件处理 压缩和兼容性处理
{
test: /\.less/,
use: [...commonCssLoader, 'less-loader']
},
/*
由于js需要被两个loader进行处理,所以需要先执行语法检查之后再来执行兼容性处理。
*/
{
// js语法检查 在package.json 中eslintConfig 进行配置
test: /\.js$/,
exclude: /node_modules/,
loader: 'eslint-loader',
// 优先执行
enforce: 'pre'
},
// js 兼容性处理
{
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
// 进行按需加载
useBuiltIns: 'usage',
// corejs 的版本
corejs: {
version: 3
},
// 需要兼容的浏览器
targets: {
chrome: '60',
ie: '9',
firefox: '60'
}
}
]
]
}
},
//图片处理
{
test: /\.(jpg|png|gif)$/,
loader: 'url-loader',
options: {
limit: 8 * 1024,
name: '[name].[hash:10].[ext]',
outputPath: 'imgs'
}
},
// html文件中的图片处理
{
test: /\.html$/,
loader: 'html-loader'
},
// 其他文件处理
{
exclude: /\.(js|css|less|html|jpg|png|gif)$/,
loader: 'file-loader',
options: {
name: '[name].[hash:10].[ext]',
outputPath: 'other'
}
}
]
},
plugins: [
// 提取css为单独文件
new MiniCssExtractPlugin({
filename: 'css/build.css'
}),
// css 压缩
new OptimizeCssAssetsWebpackPlugin(),
// 处理html文件并压缩
new HtmlWebPackPlugin({
template: './src/index.html',
minify: {
collapseWhitespace: true,
removeComments: true
}
})
],
mode: 'production'
}
三 webpack
性能优化
1. webpack
优化配置
webpack
性能优化主要是以下几个方面的优化
- 开发环境性能优化
- 生产环境性能优化
开发环境优化
- 优化打包构建速度
- 优化调试功能
生产环境优化
- 优化打包构建速度
- 优化代码运行性能
2. HMR
热模块替换
一个模块变化,只更新这一个模块,而不是所有模块,提升加载速度 开启方式:修改 devServer
的配置,追加hot: true
,即可。
样式文件:可以使用
HMR
功能,style-loader
内部实现了js
文件:默认不可用HMR
功能, 解决方法:修改js
文件javascriptif (module.hot) { // 如果module.hot 为 true,说明了开启HMR功能,让下面的功能代码生效。 module.hot.accept("./index.js", function () { ...code // 意思是指只有这个里面的方法会有HMR的效果,能够实现热模块替换 }); }
html
文件:默认也不能使用, 缺点:配置了HMR
后,html
文件也不能热更新了。 解决方法:entry
需要修改,将html
文件加入入口,并且html
文件也不需要做热更新javascriptentry: ['./src/js/index.js', './src/index.html'],
2. source-map
一种提供代码构建后映射到源代码的技术,便于构建之后追踪代码错误。
使用时,在 webpack.config.js
中配置 devtool:选项
选项有多种,
[inline-|hidden-|eval-][nosources-][cheap-[module-]]source-map
source-map
:外部生成一个映射js
,有错误代码准确信息和源代码的错误位置;inline-source-map
:内联,将映射表插入到 入口js
中,有错误代码准确信息和源代码的错误位置;hidden-source-map
:外部,有错误代码错误原因,但是没有错误位置,只能提示构建后代码错误的位置;eval-source-map
:内联,每一个文件都生成对应的source-map
,都在eval
中,构建速度最快,有错误代码准确信息和源代码的错误位置;nosources-source-map
:外部,有错误代码准确信息,但是没有任何源代码信息(不能在浏览器中断点调试);cheap-source-map
:外部,有错误代码准确信息和源代码的错误位置;cheap-module-source-map
:外部,有错误代码准确信息和源代码的错误位置,并且module
会将loader
的source map
加入;
内联 和 外部的区别:
- 外部生成了文件,内联没有
- 内联构建速度更快
开发环境:速度快,调试更友好 速度快(eval
>inline
>cheap
>...) eval-cheap-souce-map
eval-source-map
调试更友好 souce-map
cheap-module-souce-map
cheap-souce-map
一般使用开发环境使用 eval-source-map / eval-cheap-module-souce-map
生产环境:源代码要不要隐藏? 调试要不要更友好 内联会让代码体积变大,所以在生产环境不用内联
nosources-source-map
全部隐藏 hidden-source-map
只隐藏源代码,会提示构建后代码错误信息 生产环境一般使用: souce-map / cheap-module-souce-map
3. oneOf
一般情况,一个 loader
只会匹配一个类型的文件,除了 js
文件,所以一个文件应该匹配一个 loader
之后就不在匹配其他 loader。
所以在 rules
中 增加一个 oneOf:[]
包裹所有的 rules
。但是 oneOf
中同一个类型文件的 loader
只能有一个,所以需要将处理 js
的一个 loader
移动到外面。
javascript
oneOf: [
{
test: /\.css$/,
use: [...commonCssLoader]
}
]
4. 缓存
缓存从两方面入手,一方面是
babel
中,开启babel
的缓存只需要在babel
中配置一下:cacheDirectory: true
,第二次构件时,会读取之前的缓存。缓存:
babel
缓存 直接进行配置就可以 文件资源缓存:hash
:每次 webpack 生产文件都会生成唯一的hash
值, 但是js
和css
同时使用一个hash
值,如果重新打包,所有的缓存都会失效,需要重新缓存。chunkhash
:根据chunk
生成的hash
值,如果打包来源于同一个chunk
,则hash
值是同一个。 但是js
和css
是同一个入口打包的,所以chunkhash
也是相同的。contenthash
:根据文件内容生成hash
值,不同文件hash
值一定不一样。 推荐使用contenthash
,使用时在output
和css
文件名中进行配置:javascriptmodule.exports = { output: { filename: 'js/index.[contenthash:10].js', path: resolve(__dirname, 'build') }, } new MiniCssExtractPlugin({ filename: 'css/build.[contenthash:10].css' }),
5. tree shaking
能够去除无用代码 前提:
- 必须使用
ES6
模块化 - 开启
production
环境
去除无用代码能够减少代码体积,但有时有一些问题,会将没有使用的 css
文件删掉 在package.json
中配置 "sideEffects": false
所有代码都没有副作用(都可以进行tree shaking
) 增加了下面的配置,能够避免删除一些需要但是没有在index.j
调用的文件。 "sideEffects": ["*.css", "*.less"]
5. code split
代码分隔能够提升加载速度,也有一些开发平台限制单文件的大小。
- 使用单入口或者多入口实现代码分割
javascript
// 单入口
module..exrports={
entry: "./src/js/index.js";
}
// 多入口
module..exrports={
entry: {
main: './src/js/index.js',
tesst: './src/js/test.js'
},
}
- 使用
optimization
配置,可以将node_modules
中代码单独打包成一个chunk
输出,能够自动分析多入口chunk
中,有没有公共的文件,如果有则会打包成一个单独的chunk
javascript
module..exrports={
optimization: {
splitChunks: {
chunks: 'all'
}
},
}
- 在
js
中使用import
动态加载,实现代码分割:
javascript
import(/* webpackChunkName:'test' */ '../js/test.js')
.then((res) => {
console.log(res.add(1, 3))
})
.catch((err) => {
console.log(err)
})
6. lazy loading
懒加载
使用动态加载来实现懒加载,只有点击按钮时才会开始加载这个 js
还可以使用 /*webpackPrefetch:true*/
来实现预加载,预加载会在加载完其他必须的 js
后,浏览器空闲时,自动加载。避免了懒加载时,文件较大,请求时间较长的问题。 预加载的兼容性很差。
javascript
// 懒加载
document.querySelector('#btn').onclick = () => {
import('./test').then(({ add }) => {
console.log(add(7, 9))
})
// 预加载
import(/* webpackPrefetch:true */ './test').then(({ add }) => {
console.log(add(7, 9))
})
}
7. PMA
渐进式网络开发应用程序,离线也可以访问。由于兼容性有问题,普及率不高。 需要进行安装 npm i workbox-webpack-plugin -D
安装之后需要进行一些配置,主要的功能有
- 帮助 serviceworker 快速启动
- 删除旧的 serviceworker
- 生成一个 serviceworker 配置文件
javascript
new WorkboxWebpackPlugin.GenerateSW({
clientsClaim: true,
skipWaiting: true
})
在 webpack.config.js
中配置完成之后,还需要再入口文件中再配置,并且由于 eslint
不能识别 window、navigator
,所以在 package.json
还要配置
javascript
// 注册serviceWorker 注意是大写 处理兼容性问题
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker
.register('/service-worker.js')
.then(() => {
console.log('sw注册成功了~')
})
.catch(() => {
console.log('sw注册失败了~')
})
})
}
package.json
的配置:
json
"eslintConfig": {
"env": {
"browser": true
}
}
8. 多进程打包
多进程打包,有启动时间和通信时间,所以适合打包工作消耗时间较长的打包来开启。 所以适合 babel-loader
进行打包,使用 thread-loader
开启多进程打包。
javascript
module.exporrts= {
{
test: /\.js$/,
exclude: /node_modules/,
use: [
'thread-loader',
{
loader: 'babel-loader',
options: {
presets: [
[
'@babel/preset-env',
{
useBuiltIns: 'usage',
corejs: { version: 3 },
targets: {
chrome: '60',
firefox: '50'
}
}
]
],
cacheDirectory: true
}
}
]
},
}
9. externals
externals
配置,可以忽略要打包的包名,例如要使用 cdn
加载 jquery
就可以忽略掉 jquery
打包,再 index.html
中引入 cdn
即可。
javascript
module.exports={
externals: {
// 要忽略的打包的包名
jquery: "jQuery";
}
}
10. dll
实际上是将需要使用的第三方包 jquery、react、vue
先进行打包,最后打包自己的 js
文件时就可以免去打包第三方包的步骤。 需要新建一个 webpack.dll.js
文件,进行一些基本的配置:
javascript
const { resolve } = require('path')
const webpack = require('webpack')
module.exports = {
entry: {
// 最终打包生成的[name] --> jquery
// ['jquery'] --> 要打包的库是jquery
jquery: ['jquery']
},
output: {
filename: '[name].js',
path: resolve(__dirname, 'dll'),
library: '[name]_[hash]' // 打包的库里面向外暴露出去的内容叫什么名字
},
plugins: [
// 打包生成一个 manifest.json --> 提供和jquery映射
new webpack.DllPlugin({
name: '[name]_[hash]', // 映射库的暴露的内容名称
path: resolve(__dirname, 'dll/manifest.json') // 输出文件路径
})
],
mode: 'production'
}
命令行中使用 webpack --config webpack.dll.js
提前将第三方包进行打包,然后使用 add-asset-html-webpack-plugin
将之前打包出去的包,在自己的项目打包时,引用进来。
注: webpack
包也是必须要引入的。
javascript
const webpack = require('webpack')
const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin')
module.exports = {
plugins: [
new AddAssetHtmlWebpackPlugin({
filepath: resolve(__dirname, 'dll/jquery.js')
})
]
}
四 webpack
配置详细介绍
1. entry
配置
entry
入口的值有三种情况
string
:'./src/js/index.js'
打包形成一个chunk
,只会输出一个文件,此时chunk
的默认名称为main
array
:['./src/js/index.js', './src/js/add.js']
, 所有入口文件最终只会形成一个chunk
,只会输出一个文件。 一般只有 HMR 功能中才会使用object
:{ index: './src/js/index.js', add: './src/js/add.js' }
有几个入口文件就会形成几个chunk
,也会输出几个文件。特殊用法,所有文件最终只会形成一个
chunk
,输出只有一个文件javascript{ index:['./src/js/index.js', './src/js/add.js'], add:'./srrc/add.js' }
2. output
配置
javascript
module.exports = {
entry: './src/js/index.js',
output: {
// filename 文件名称 + 目录
filename: './js/[name].js',
// path 只能指定文件目录
path: resolve(__dirname, 'build'),
// 所有资源引入的公共路径前缀 例如:imgs/a.jpg ,打包之后地址变为 /imgs/a.jpg
publicPath: '/',
// 非入口 chunk 的名称
chunkFilename: '[name]_chunk.js',
// 整个库向外暴露的变量名,一般配合 DLL 进行使用
library: '[name]',
// 变量名添加到哪个变量上
libraryTarget: 'window'
// libraryTarget:'global'
},
plugins: [new HtmlWebPackPlugin()],
mode: 'development'
}
3. module
配置
javascript
rules: [
// loader 配置
{
test: /\.css$/,
// 多个用use
use: ['style-loader', 'cs-loader']
},
{
test: /\.js$/,
// 排除
exclude: /node_module/,
// 只检查 src 下的js文件
include: resolve(__dirname, 'src'),
// 单个用loader
loader: 'eslint-loadere',
// 优先执行
enforce: 'pre'
// 延后执行
// enforce: 'post'
},
{
// 以下配置只会生效一个
oneOf: []
}
]
4. resolve
配置
用于配置解析模块路径别名
javascript
// 解析模块的规则
resolve: {
// 配置解析模块路径别名:能够在js引入import时,简写路径
alias: {
$css: resolve(__dirname, 'src/csss')
},
// 配置省略文件路径的后缀名
extensions: ['.js', 'json'],
// 解析模块时去哪个目录找, 默认是 node_modules
modules: ['node_modules']
}
5. DevServer
配置
javascript
devServer: {
// 运行代码的目录
contentBase: resolve(__dirname, 'build'),
// 监视contentBase目录下的文件,一旦变化就 重载
watchContentBase: true,
// 忽略监视的文件
watchOptions: {
ignored: /node_modules/
},
// 开启压缩
compreesss: true,
// 端口号
port: 5000,
// 域名
host: 'localhost',
// 开启HMR
hot: true,
// 不要显示启动服务器日志
clientLogLevel: 'none',
// 除了启动信息,其他内容都不显示
quite: true,
// 如果出错了,不要全屏显示
overlay: false,
// 服务器代理,解决开发环境跨域代理
proxy: {
// 一旦devServer(5000)服务器接受到 /api/xxx 的请求,就会把请求转发到另外一个服务器(3000)
'/api': {
target: 'http://localhost:3000',
// 发送请求时,请求路径重写:将 /api/xxx 转换为 /xxx (去掉/api)
pathRewrite: {
'^/api': ''
}
}
}
}
6. optimization
配置
javascript
optimization: {
splitChunks: {
chunks: 'all'
// 默认值,以下都是默认值,跨域不写
/* minSize: 30 * 1024, // 分割的chunk最小为30kb
maxSiza: 0, // 最大没有限制
minChunks: 1, // 要提取的chunk最少被引用1次
maxAsyncRequests: 5, // 按需加载时并行加载的文件的最大数量
maxInitialRequests: 3, // 入口js文件最大并行请求数量
automaticNameDelimiter: '~', // 名称连接符
name: true, // 可以使用命名规则
cacheGroups: {
// 分割chunk的组
// node_modules文件会被打包到 vendors 组的chunk中。--> vendors~xxx.js
// 满足上面的公共规则,如:大小超过30kb,至少被引用一次。
vendors: {
test: /[\\/]node_modules[\\/]/,
// 优先级
priority: -10
},
default: {
// 要提取的chunk最少被引用2次
minChunks: 2,
// 优先级
priority: -20,
// 如果当前要打包的模块,和之前已经被提取的模块是同一个,就会复用,而不是重新打包模块
reuseExistingChunk: true
}
}*/
},
// 将当前模块的记录其他模块的hash单独打包为一个文件 runtime
// 解决:修改a文件导致b文件的contenthash变化
runtimeChunk: {
name: entrypoint => `runtime-${entrypoint.name}`
},
minimizer: [
// 配置生产环境的压缩方案:js和css
new TerserWebpackPlugin({
// 开启缓存
cache: true,
// 开启多进程打包
parallel: true,
// 启动source-map
sourceMap: true
})
]
}