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. webpack5 个核心概念
entryoutputloaderpluginsmode
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-serverwebpack5:npx webpack servewebpack.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文件,还有其它的如:lessscssstyls等的处理,不过此处以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-mapsource-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-mapeval-source-map 调试更友好 souce-mapcheap-module-souce-mapcheap-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的默认名称为mainarray:['./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
})
]
}