一、多页面构建(MPA)
前言:一个ssr的多页面(MPA)应用,利于seo,每个页面为单独模块
二、解析引擎 - 解析打包 webpack.base.js
入口配置
js
entry:{ // 多页面ssr应用
"entry.page1":'./app/pages/page1/entry.page1.js',
"entry.page2":'./app/pages/page2/entry.page2.js',
},
loader解析配置
- vue=>
vue-loader
- js=>
bable-loader
- css=>
style-loader
,css-loader
,less-loader
- png=>
file-loader
plugins 插件配置
VueLoaderPlugin
- 处理.vue 文件,这个插件是必须的
- 他的职能是将你定义的其他规则复制并应用到.vue文件里 ,解析scrpt和style模块
- 例如,如果有一条匹配规则/.js$/的规则,那么他会应用到。vue文件中模块中
htmlWebpackPlugin
js
new HtmlWebpackPlugin({
// 产物 (最终模版)输出路径
filename:path.resolve(process.cwd(),'./app/public/dist/','entry.**.tpl'),
// 指定要使用的模版文件
template:path.resolve(process.cwd(),'./app/view/entry.tpl'),
//要注入的代码块
chunks:['entry.page1']
}),
分包
把js文件打包成3种类型
vendor
:第三方lib库,基本不会改动,除非依赖版本升级common
:业务组件代码的公共部分抽取出来,改动较少
js
optimization:{
splitChunks:{
chunks:'all', //对同步异步都进行分割
maxAsyncRequests:10,// 每次异步记载的最大并行请求数
maxInitialRequests:10,// 入口点的最大并行请求数
cacheGroups:{
vendor:{// 第三方依赖库
test:/[\\/]node_modules[\\/]/,// 打包node_module中的文件
name:'vendor',// 模块名称
priority:20,// 优先级
enforce:true,// 强制执行
reuseExistingChunk:true//复用已有的公共 chunk
},
common:{// 公共模块
// test:/[\\/]common|widgets[\\/]/,
name:'common',// 模块名称
minChunks:2,// 被复用次数(被2处引用即被归为公共模块)
minSize:2,// 最小分割文件大小
priority:10,// 优先级
reuseExistingChunk:true//复用已有的公共chunk
}
}
},
}
模版渲染
使用koa-nunjucks-2
插件
tpl模版地址为:/app/public/dist/entry.**.js
less
注册 koaNunjucks 中间件
const koaNunjucks = require('koa-nunjucks-2');
app.use(KoaStatic(path.resolve(process.cwd(),'./app/public')))
app.use(koaNunjucks({
ext: 'tpl', // 模版文件
path: path.join(process.cwd(), './app/public'),
nunjucksConfig: {
noCache :true, // 不使用缓存,每次重新编译
trimBlocks: true // 去除换行符
}
渲染tpl模版
ctx.render(`dist/entry.${ctx.params.page}`,{自定义传参})
webpack基础配置
css
entry:{
"name":'入口文件地址'
},
modele:{
rules:[{
...loader
}]
},
output:{输出},
plugins:[插件],
reslove:{},
optimization:{
splitchunks
},
mode:''

生产 webpack.prod.js
利用缓存打包
js
optimization:{
//使用TerserPlugin 的并发和缓存,提升压缩阶段的性能
//清除console。log
minimize:true,
minimizer:[
new TerserWebpackPlugin({
cache:true, // 启用缓存来加速构建过程
parallel:true,// 利用多核cpu的优势来加快压缩速度
terserOptions:{
compress:{
drop_console:true// 去除console.log 内容
}
},
extractComments:false // 禁止提取注释到单独文件
})
],
}
多线程打包 js css
使用happyPack
多线程打包
css 缓存,压缩
使用MiniCssExtractPlugin
提取css公共部分,有效利用缓存,使用CssMinimizerPlugin
打包压缩css
开发 webpack.dev.js
js
const webpackDevConfig = merge.smart(baseConfig,{
mode:'development',
// source-map 开发工具,呈现代码映射关系。便于开发过程中调试代码
devtool:'eval-cheap-module-source-map',
// 开发阶段 output 配置
output:{
filename:'js/[name]_[chunkhash:8].bundle.js',
path:path.resolve(process.cwd(),"./app/public/dist/dev/"),// 存储路径
publicPath:`http://${HOST}:${PORT}/public/dist/dev/`, // 外部资源公共路径
globalObject:'this'
},
plugins:[
// HotModuleReplacementPlugin 用于实现热模块替换 hmr
// 模块热替换允许应用程序运行时替换模版
// 极大的提升开发效率,因为能让应用程序一直保持运行状态
new webpack.HotModuleReplacementPlugin({
multStep:false
})
]
})
热更新
hmr 热更新: 书写业务代码->监控文件改动-> 通知解析引擎解析打包压缩-> template 发送客户端 公共部分发送服务端-> 服务端通知客户端变化-> 客户端加载template和公共资源重新展示

devmiddleware
中间件(监控文件改动)
hotmiddleware
中间件(实现热更新通讯)
js
app.use(webpackDevMiddleware(compiler,{
writeToDisk:(filePath)=>filePath.endsWith('.tpl'),
//资源路径
publicPath:webpackDevConfig.output.publicPath,
// headers 配置
headers:{
"Access-Control-Allow-Origin":'*',
"Access-Control-Allow-Methods":'GET,POST,PUT,DELETE,PATCH,OPTIONS',
"Access-Control-Allow-Headers":"Content-Type, X-Requested-With, Authorization"
},
stats:{
colors:true
}
}))
const {PORT,HMR_PATH} = DEV_SERVER_CONFIG
app.use(webpackHotMiddleware(compiler,{
path:`/${HMR_PATH}`, // 与devmiddleware的publicPath组合成完整地址
log:()=>{}
}))
补充: webpack5 自带的原生打包工具thread-loader 多线程打包
js
rules: [{
test: /.js$/,
use: [
{
loader: 'thread-loader',
options: { workers: os.cpus().length - 1 }
},
{
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
plugins: ['@babel/plugin-transform-runtime']
}
}
]
}]