本节重点讲解解析器 resolve的配置 和 其他插件 plugins的配置
一、resolve
配置项详解:
- modules: 告诉webpack 解析模块是应该搜索的目录,即import * from ‘*’ 时应该搜索的目录
- alias: 项目中 使用import 或者require 时的别名
- enforceExtension: enforceExtension如果是true,将不允许无扩展名(extension-less)文件,默认如果 ./foo 有 .js 扩展,require('./foo') 可以正常运行。但如果启用此选项,只有require('./foo.js') 能够正常工作
- extensions: 自动解析确定的扩展, 在引入模块时不带扩展 import File from '../path/to/file',不需要带扩展.js .less 等等
resolve: {
modules: [path.resolve(__dirname, 'src'), 'node_modules'],
alias: {
'@': path.resolve(__dirname, './src'),
'api': path.resolve(__dirname, './src/publics/Api'),
'util': path.resolve(__dirname, './src/publics/common/util'),
'Comps': path.resolve(__dirname, './src/components'),
'Form': path.resolve(__dirname, './src/components/Form'),
'Hoc': path.resolve(__dirname, './src/components/Hoc'),
'globalRedux': path.resolve(__dirname, './src/redux'),
'hooks': path.resolve(__dirname, './src/publics/common/hooks'),
}
/* resolve.enforceExtension如果是 true,将不允许无扩展名(extension-less)文件。默认如果 ./foo 有 .js 扩展,require('./foo') 可以正常运行。但如果启用此选项,只有 require('./foo.js') 能够正常工作。 */
enforceExtension: false,
extensions: ['.js', '.jsx', '.json', '.css', '.less']
}
}
以上 alias,例如,在page目录下 引入文件的原本路径为: import Input from '../component/Form/Input' 简化路径可以修改为: import Input from ’Form/Input‘
二、一些补充的plugins
一、NamedModulesPlugin
用于启动HMR 热更新时可以显示模块的相对路径,多用于开发环境development
new webpack.NamedModulesPlugin()
new webpack.HotModuleReplacementPlugin()
二、HotModuleReplacementPlugin
模块热更新,即局部更新的插件,多用于开发环境
三、开发环境启动浏览器 使用webpack-dev-server
配置详情:
devServer: {
contentBase: '/', //静态文件的文件夹地址,默认为当前文件夹 为根文件夹提供本地服务器,如果想为另外一个目录下的文件提供本地服务器,应该在这里设置其所在目录
port: 3000, // 监听端口
historyApiFallback: true,
//colors: true, // 使用颜色,有利于找出关键信息,只能在控制台中使用
hot: true, // 启用热替换属性
// hotOnly: true, // 开启该属性之后 修改js文件不会刷新页面
//info: true, //· 在控制台输出信息,默认输出
open: true, // 运行命令之后自动打开浏览器
progress: true //将运行进度输出到控制台,只可以使用控制台
},
上述配置也可以在 package.json里通过script 启动命令时配置:
"start": "cross-env ENV=development webpack-dev-server --open --colors --config webpack.dev.js",
四、优化 optimization 生产环境配置项(压缩,分包等)
首先明确webpack里module。chunk。bundle的意义
1.module:就是js的模块化webpack支持commonJS、ES6等模块化规范,简单来说就是你通过import语句引入的代码。
2.chunk: chunk是webpack根据功能拆分出来的,包含三种情况
3.bundle:bundle是webpack打包之后的各个文件,一般就是和chunk是一对一的关系,bundle就是对chunk进行编译压缩打包等处理之后的产出。 chunk 包含的三种情况:
1)、你的项目入口(entry)
2)、通过import()动态引入的代码
3)、通过splitChunks拆分出来的代码,chunk包含着module,可能是一对多也可能是一对一
webpack的优化配置一般在 optimization 选项里,主要有如下几项:
- splitChunks webpack分包打包js策略 optimization.splitChunks抽离第三方库,内部其实使用了split-chunks-plugin插件。将业务代码、第三方类库、runtime 代码、css 单独打包,给他们不同 hash,来最大化利用缓存
- runtimeChunk 是否抽离webpack runtime到单独的文件
- minimizer 压缩器,webpack4 中使用 terser-webpack-plugin 来替代之前的 uglifyjs-webpack-plugin 压缩器(需要npm 安装),css压缩使用 optimize-css-assets-webpack-plugin
module.exports = {
//...
optimization: {
splitChunks: {
/*
*chunks属性用来选择分割哪些代码块,可选值有:'all'(所有代码块),'async'(按需加载的代码块),'initial'(初始化代码块)
*initial:告诉webpack,将动态导入的文件和非动态导入的文件分别打包,如果一个模块被动态引入,也被非动态引入。那么这个模块将会被分离2次。被分别打包到不同的文件中。
* */
chunks: 'all',
minSize: 120 * 1024, // 抽离体积大于120kb的chunk
minChunks: 2, // 抽离被多个入口引用次数大于等于1的chunk
automaticNameDelimiter: '--', // 分包打包生成文件的名称的连接符
cacheGroups: { // cacheGroups 缓存组,如:将某个特定的库打包
/* 抽离node_modules下的第三方库 可视需要打开会生成两个文件 vender: node-module下的文件*/
vendor: {
chunks:'all',
name:'vender',
test: (module, chunks) => {
if (/node_modules/.test(module.context)) {
return true
}
},
minChunks: 2,// 提取公共部分最少的文件数
priority: 10,
enforce: true
},
/* 提取共用部分,一下提取的部分会议commons 命名 */
commons: {
name: 'commons',
test: function (module, chunks) {
if (/src\/components\//.test(module.context) ||
/src\/common\/util\//.test(module.context) ||
/react/.test(module.context) ||
/react-dom/.test(module.context) ||
/moment/.test(module.context) ||
/redux/.test(module.context)) {
return true
}
},
chunks: 'all',
minChunks: 2, // 提取公共部分最少的文件数
minSize: 0 // 提取公共部分最小的大小
// enforce: true
}
}
},
minimizer: [
new TerserPlugin({ // 压缩js
cache: true,
parallel: true,
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true // 去除console.log 和debuger
},
}),
new OptimizeCSSAssetsPlugin({}) // 压缩css
]
}
};