如今我们打包和工程化,大部分是webpack进行,webpack的更新迭代速度也是很可观的,官网如今已经更新到4.40.2版本,同样的相关的配置也都在简化,具体的配置就不在赘述。
网上有很多大佬都记录了从webpack3升级到webpack4踩得坑,有兴趣和需要的小伙伴可以自行度娘下,在此只简单记录下公共文件抽离的配置及引入。
项目是自己练习简单搭建的,看下基本结构,只简单写下涉及到的结构:
|---- 根目录
|---- node_modules
|---- src
|---- css
|---- images
|---- js //各个模块引入的js文件
|---- a.js
|---- b.js
|---- App.vue //vue主页面
|---- index.js //index页面需要的js
|---- file.js //file页面需要的js
|---- index.html //多页面index页
|---- file.html //多页面file页
|---- webpack.config.js //基础webpack配置
|---- webpack.dev.config.js //开发配置
|---- webpack.prod.config.js //生产配置
|---- webpack.dll.config.js //抽包配置
基本的页面就不上代码了,都是基本结构,两个入口js都共同引入了a.js和b.js文件,index.html只引入index.js,file.html只引入file.js文件,模拟一个多页面的效果。
基本webpack不在赘述,使用基本配置打包后我们会发现index.js文件会很大,而且打包速度很慢,因为我们引入了vue以及公共的js文件,现在我们开始对文件进行分离。主要使用两个配置功能,DllPlugin:抽离vue,vuex等;optimization:抽离公共引入的文件。
先看下基本抽包配置:webpack.dll.config.js
const path = require('path')
const Webpack = require('webpack')
module.exports = {
mode: 'production',
entry: {
vue: ['vue']
},
output: {
filename: '[name].dll.js',
path: path.resolve(__dirname, '.dll'),
library: '[name]',
libraryTarget: 'var'
},
plugins: [
new Webpack.DllPlugin({
name: '[name]',
path: path.resolve(__dirname, './dll', '[name].manifest.json'),
context: __dirname
})
]
}
基本配置完成后,我们可以直接在webpack.prod.config.js里使用DllReferencePlugin引入,但是这种方法不够灵活,我们采用遍历方法,把dll里边的文件自动引入。同时我们使用optimization抽离公共文件及引用。
//=====webpack.config.js
......引入插件略
const plugins = [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
template: './index.html',
filename: 'index.html',
chunks: ['index']
})
]
//获取抽包文件,自动添加到html页面中
const files = fs.readdirSync(path.resolve(__dirname, './dll'));
files.forEach(file => {
if(/.*\.dll\.js/.test(file)){
plugins.push(
new AddAssentHtmlWebpackPlugin({
filepath: path.resolve(__dirname, './dll', file)
})
)
}
if(/.*\.manifest.json/.test(file)){
plugins.push(
new Webpack.DllReferencePlugin({
manifest: path.resolve(__dirname, './dll', file)
})
)
}})
module.exports = {
entry: {
index: './src/index.js',
file: './src/file.js'
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'build'),
publicPath: '/'
},
plugins: plugins,
optimization: {
//各个模块的引用和加载逻辑单独抽出,嵌入每个entry
runtimeChunk: {
name: 'manifest'
},
//抽离各个模块的公共引用文件
splitChunks: {
cacheGroups: {
common: {
chunks: 'initial', //开始就要抽离公共模块
minSize: 0,
minChunks: 2
}
}
}
}
.......其他配置略
}
对于单页面应用我们这么配置是没问题的,优先执行下抽包命令“webpack --config webpack.dll.config.js”,然后执行打包命令,可以成功打包。但是此时问题出现了,我们打开页面,发现页面并不是我们预期的效果,而且并没有什么报错。通过查看网络请求我们发现我们通过optimization抽出的公共文件没有成功引入,此处也是一个小坑。
此时我们去看package.json里的html-webpack-plugin,发现版本依旧是3点几的版本,有大佬说这是webpack的遗留问题,此插件没有更新,我们需要手动更新到4版本,‘npm install html-webpack-plugin@4.0.0-alpha.2’,再执行命令打开,发现问题解决了;
上面是对单页面的处理,如果我们涉及的是多页面的情况呢,有小伙伴可能会说多引用几次HtmlWebpackPlugin不就可以了吗,确实如此。但是操作也不够灵活,此处,我们也把这个插件的引用写活(此处我是根据js文件判断的名字,实际可以根据导航、路由等其他方式判断),对基本配置进行修改
//=====webpack.config.js
......引入插件略
const plugins = [
new CleanWebpackPlugin()
]
//获取js文件,动态的添加到htmlwebpackplugin页面中
const jsFiles = fs.readdirSync(path.resolve(__dirname, './src'))
jsFiles.forEach(js=>{
if(/.*\.js/.test(js)){
let jsName = js.split('.')[0]
plugins.push(
new HtmlWebpackPlugin({
template: `./${jsName}.html`,
filename: `${jsName}.html`,
minify: {
removeAttributeQuotes: true,
collapseWhitespace: true
},
inject: true,
hash: true,
chunks: [`${jsName}`]
})
)
}})
//获取抽包文件,自动添加到html页面中
const files = fs.readdirSync(path.resolve(__dirname, './dll'));
files.forEach(file => {
if(/.*\.dll\.js/.test(file)){
plugins.push(
new AddAssentHtmlWebpackPlugin({
filepath: path.resolve(__dirname, './dll', file)
})
)
}
if(/.*\.manifest.json/.test(file)){
plugins.push(
new Webpack.DllReferencePlugin({
manifest: path.resolve(__dirname, './dll', file)
})
)
}})
module.exports = {
entry: {
index: './src/index.js',
file: './src/file.js'
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, 'build'),
publicPath: '/'
},
plugins: plugins,
optimization: {
//各个模块的引用和加载逻辑单独抽出,嵌入每个entry
runtimeChunk: {
name: 'manifest'
},
//抽离各个模块的公共引用文件
splitChunks: {
cacheGroups: {
common: {
chunks: 'initial', //开始就要抽离公共模块
minSize: 0,
minChunks: 2
}
}
}
}
.......其他配置略
}
这样我们就可以根据文件内容自动配置html相关名字和引用了,即使后面再增加页面,我们只需要增加对应的文件即可,不用再重新进行配置。
webpack配置可以说是博大精深,各人有各人的配置方法,但是我们的目的是一样的,加快打包和运行时的加载速度。文章写得比较急,有错误和不足的地方希望各位多多指点,大家共同学习~