之前我们打包,实际上都是对
单页面应用
进行的打包
什么叫做单页面应用
呢?
- 整个应用里边只有一个
html文件
,就是单页面应用;比如我们之前的例子,当我们运行npm run build
的时候,dist目录里,只有一个idnex.html
image.png - 现在主流框架,
vue
,react
都是单页面应用,所以webpack做打包的时候,绝大多数场景都是对单页面应用进行打包;但是在一些特殊的场景下,比如兼容一些jquery
的老的项目,或者zepto
这样的老的项目,包括一些特别奇怪的场景之中,我们确实会遇到要对多页面应用进行打包的场景
那么该怎么实现对多页面应用的打包呢?
之前,我们通过html-webpack-plugin
这个插件,打包之后会在dist
目录下生成一个index.html
文件,并且文件里会引入打包生成的main.js
文件
-
现在假如我们有另外一个页面
image.pnglist.js
,我们希望打包之后,webpack会生成一个list.html文件,而且在list.html文件里只引入打包生成的list.js
文件。而原来的index.html文件,只引入main.js
文件
-
我们先配置入口文件
image.png
image.png -
我们可以这样配置
image.pnghtml-webpack-plugin
,意思是打包的时候,以src
目录下的index.html
为模板,分别生成一个index.html文件和list.html文件,filename
是html-webpack-plugin
这个插件的属性,更多属性可以到github去查
-
配置好以后,我们再重新打包,可以看到,生成的dist文件夹下,有index.html和list.html文件了
image.png -
但是无论是index.html 还是list.html ,里边都同时引入了
image.pngmain.js
和list.js
;这不是我们想要的,我们的目标是 index.html文件里引入main.js
,而list.html里引入list.js文件
-
针对这种问题,我们该怎么解决呢,我们还可以给
image.pnghtml-webpack-plugin
再配置一个参数chunks
,这个配置的意思是,这个html文件要引入的打包生成的js文件有哪些;其中runtime.js
和venfors.js
是两个html文件都需要的
-
配置好后,我们再进行打包,可以看到dist.html出了公用的js文件,只引入了
image.pnglist.js
;而 index,html里只引了main.js
image.png -
而这两个文件也是可以正常运行的
image.png
image.png
经过上边的配置,我们就实现了多页面应用的打包。它的实现方式,实际上就是调整入口文件配置
。和配置多个html-webpack-plugin
而已
虽然我们上边实现了多页面应用的配置,但是我们是手动的,只有两个页面,如果有很多页面,我们是不是要手动去增加多个入口文件,并且增加多个html-webpack-plugin
? 很明显这种方式是效率低下的,有没有方式能智能的帮我们实现这个目标呢?
const path = require('path');
const fs = require('fs');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const AddAssetHtmlWebpackPlugin = require('add-asset-html-webpack-plugin')
const webpack = require('webpack');
// 写一个函数,用来生成 plugins,这个函数接收 confis参数
const makePlugins = (configs) => {
// 创建一个plugins 数组,初始只有CleanWebpackPlugin 这个插件
const plugins = [
new CleanWebpackPlugin(['dist'], {
root: path.resolve(__dirname, '../')
})
]
// 获取到 configs的entry配置,入口配置有几个key,打包的时候,就生成几个 html文件, 文件名是key值
Object.keys(configs.entry).forEach(item => {
plugins.push(
new HtmlWebpackPlugin({
template: 'src/index.html',
filename: `${item}.html`,
chunks:['runtime','vendors',item]
})
)
})
// 读取到dll文件夹下的文件,然后遍历,并根据后缀名,使用使用不同的插件
const files = fs.readdirSync(path.resolve(__dirname, '../dll'));
files.forEach((file) => {
if (/.*\.dll.js/.test(file)) {
plugins.push(
new AddAssetHtmlWebpackPlugin({
filepath: path.resolve(__dirname, '../dll', file)
})
)
}
if (/.*\.manifest.json/.test(file)) {
plugins.push(
new webpack.DllReferencePlugin({
manifest: path.resolve(__dirname, '../dll', file)
})
)
}
})
return plugins
}
// 把配置复制给一个变量 configs
const configs = {
entry: {
index: './src/index.js',
list: './src/list.js'
},
resolve: {
extensions: ['.js', '.jsx']
},
module: {
rules: [{
test: /\.jsx?$/,
include: path.resolve(__dirname, '../src'),
use: [{
loader: 'babel-loader'
}]
}, {
test: /\.(jpg|png|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name]_[hash].[ext]',
outputPath: 'images/',
limit: 10240
}
}
}, {
test: /\.(eot|ttf|svg)$/,
use: {
loader: 'file-loader'
}
}]
},
optimization: {
runtimeChunk: {
name: 'runtime'
},
usedExports: true,
splitChunks: {
chunks: 'all',
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
name: 'vendors',
}
}
}
},
performance: false,
output: {
path: path.resolve(__dirname, '../dist')
}
}
// 通过makePlugins 函数给 configs的plugins属性赋值
configs.plugins = makePlugins(configs);
// 导出configs
module.exports = configs
通过上边的配置。如果我们再增加页面,值需要在src下新增一个js文件,然后再去入口文件新增一个配置就醒了。
-
比如我们新增了 detail页面
image.png -
修改entry配置
image.png -
再次打包,生成了detail.html,而且可以正常运行
image.png
image.png
网友评论