摘要:多页面中公用js及scss代码的抽取
一、知识点
- html-webpack-plugin:chunks属性。
- webpack.optimize.CommonsChunkPlugin:name和minChunks属性。
- 公用scss代码仍需要在入口文件中引用而不是在各自的scss文件中通过@import引用。
- 提取的公共模块文件,只是入口文件本身的业务代码变化,重新构建后提取的公共模块文件名仍保持不变,保证了浏览器的缓存作用。
二、配置代码
const webpack = require('webpack');//防止重复,抽取公共模块
plugins.push(//公共模块抽取
new webpack.optimize.CommonsChunkPlugin({
name: 'js/com/common', // 指定公共 模块 的名称。
minChunks:2, //(模块必须被2个 入口chunk 共享),只要是被两个及以上的chunk引用的公共代码都会被打包到公共模块中
//chunks: ["js/pages/PageA", "js/pages/PageB"],
// (只使用这些 入口chunk)
})
);
//生成html配置
plugins.push(new HtmlWebpackPlugin({
// 生成出来的html文件名
filename: distDir+'/html/'+ outputHtmlName + '.html',
// 每个html的模版,这里多个页面使用同一个模版
template:srcDir + '/html/'+ outputHtmlName + '.html',
// 自动将引用插入body
inject: 'body',
title:outputHtmlName,
// 每个html引用的js模块,也可以在这里加上vendor等公用模块
chunks: [entryFileName,'js/com/common']//在这里增加对公共模块的引用
}));
三、完整配置
const path = require('path');
const glob = require("glob");
const HtmlWebpackPlugin = require('html-webpack-plugin'); //多页面配置插件
const ExtractTextPlugin = require('extract-text-webpack-plugin'); // css 单独打包插件,使用可看官方文档
const CleanWebpackPlugin = require('clean-webpack-plugin');//用于在构建前清除dist目录中的内容
const webpack = require('webpack');//防止重复,抽取公共模块
const srcDir = path.resolve(__dirname, './src');
const distDir = path.resolve(__dirname, './dist');
const plugins = [];
const entrys = getEntry();
//获取多页面的每个入口文件,用于配置中的entry
function getEntry() {
let files = glob.sync(srcDir+'/js/**/*.js'),
entry = {},
entryFileName,
outputHtmlName;
for(let i = 0; i < files.length; i++){
let matchs = /js\/(\S*).js/.exec(files[i]);
entryFileName = outputHtmlName = matchs[1]; //得到apps/question/index这样的文件名
if(/^_\w*/.test(entryFileName) || /\/_\w*/.test(entryFileName) || /(com|lib)\//.test(entryFileName))
{
continue;
}
entryFileName = 'js/'+entryFileName;
entry[entryFileName] = files[i]
//生成html配置
plugins.push(new HtmlWebpackPlugin({
// 生成出来的html文件名
filename: distDir+'/html/'+ outputHtmlName + '.html',
// 每个html的模版,这里多个页面使用同一个模版
template:srcDir + '/html/'+ outputHtmlName + '.html',
// 自动将引用插入body
inject: 'body',
title:outputHtmlName,
// 每个html引用的js模块,也可以在这里加上vendor等公用模块
chunks: [entryFileName,'js/com/common']
}));
}
console.log('> entry' + JSON.stringify(entry))
return entry;
}
entrys.vendor = ['jquery','d3'];
//抽取css到单独文件
plugins.push(
new ExtractTextPlugin({
filename: (getPath) => {
return getPath('css/[name].css').replace('css/js', 'css')
},
allChunks: true
})
);
//清除dist构建目录文件
plugins.push(new CleanWebpackPlugin(['dist']));
plugins.push(//公共模块抽取
new webpack.optimize.CommonsChunkPlugin({
name: 'js/com/common', // 指定公共 bundle 的名称,表示出了生成后的目录
minChunks:2, //(模块必须被2个 入口chunk 共享),只要是被两个及以上的chunk引用的公共代码都会被打包到公共模块中
//chunks: ["js/pages/PageA", "js/pages/PageB"],
// (只使用这些 入口chunk)
})
);
module.exports = {
// JS 执行入口文件
entry:getEntry(),
output: {
//多文件输出
filename: '[name]_[chunkhash:8].js',// 给输出的文件名称加上 Hash 值
// 输出文件都放到 dist 目录下
path: distDir,
},
resolve: { //配置别名,在项目中可缩减引用路径
alias: {
jquery: srcDir + "/js/lib/jquery-3.3.1.js",
d3: srcDir + "/js/lib/d3_3.2.8.js",
}
},
module: {
rules: [
{
test: /\.vue$/,
use: ['vue-loader'],
},
/*{//css打包到js中
test: /\.scss/,
use: [{
loader: 'style-loader'
}, {
loader: 'css-loader'
}, {
loader: 'sass-loader'
}]
}*/
{//css单独打包
test: /\.scss/,
use: ExtractTextPlugin.extract({
use: [{
loader:"css-loader"
},{
loader: 'sass-loader'
}],
fallback: "style-loader"
})
}
]
},
plugins:plugins,
devtool: 'source-map' // 输出 source-map 方便直接调试 ES6 源码
};
四、更加详细多样的解决方法请参见官网:https://doc.webpack-china.org/plugins/commons-chunk-plugin/