渐进式配置webpack4单页面和多页面
前言
使用包的版本
webpack ->4.3.0
babel-loader ->8.0.5
npm ->6.4.1
webpack-cli ->3.3.1
每个章节对应一个demo
构建多页面配置
具体代码参考demo12
新建多页面目录
新建module文件,约定module目录里面每个文件目录必须有个html文件,还有一个与其名字相同的js文件作为入口文件。
创建变量函数
在build文件夹里面的help.js里面新建方法
/**
* @description: 遍历文件夹里面的所有文件
* @param {array} [路径地址]
* @return: {文件名:文件地址}
*/
exports.getEntry = function getEntry(globPath) {
var entries = {};
if (typeof(globPath) != "object") {
globPath = [globPath]
}
globPath.forEach((itemPath) => {
// glob.sync 同步读取
glob.sync(itemPath).forEach(function(entry) {
entries[entry.substring(13, entry.lastIndexOf('.'))] = entry; // 13代表'./src/module/'
});
});
return entries;
};
引入多页面文件
在 webpack.base.js里面引入多页面入口文件
var entries = help.getEntry(['./src/module/**/*.js']); // 获得入口js文件
console.log(entries);
/**
打印结果
{ 'demo/demo': './src/module/demo/demo.js',
'test/test': './src/module/test/test.js' }
**/
添加到入口文件
entry:Object.assign({},{app:help.resolve('./app.js')},entries),
在 webpack.base.js里面引入多页面的html文件
function concatHtmlWebpackPlugin() {
var entriesHtml = help.getEntry(['./src/module/**/*.html']);
console.log(entriesHtml)
/**
打印结果
{ 'demo/demo': './src/module/demo/demo.html',
'test/test': './src/module/test/test.html' }
**/
var res = [];
for (var i in entriesHtml) {
var html = entriesHtml[i];
var obj = new htmlWebpackPlugin({
filename: '.' + html.substring(html.lastIndexOf('/')),
template: html, //html模板路径
inject: true, //允许插件修改哪些内容,包括head与body
chunks: ['vendors',i],//i代表入口文件的key 指定注入某些入口文件
minify: {
// 压缩 HTML 文件
removeComments: isPord, // 移除 HTML 中的注释
collapseWhitespace: isPord, // 删除空白符与换行符
minifyCSS: isPord // 压缩内联 css
},
})
res.push(obj)
}
return res
}
注入多页面
plugins:[
new htmlWebpackPlugin({
filename:'index.html',
template:'./index.html',
inject:true,
chunks: ['vendors','app'], // 指定注入某些入口文件
minify: {
// 压缩 HTML 文件
removeComments: isPord, // 移除 HTML 中的注释
collapseWhitespace: isPord, // 删除空白符与换行符
minifyCSS: isPord // 压缩内联 css
},
})
].concat(concatHtmlWebpackPlugin())
splitChunks 进行默认配置
optimization: {
splitChunks: {
chunks: 'async',
minSize: 30000,
maxSize: 0,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: '~',
name: true,
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
},
运行命令
npm run dev
多页面拆包配置
具体代码参考demo12
每个页面的js文件引入各种包
src/module/demo/demo.js
import axios from 'axios';
import xlsx from 'xlsx';
import dropzone from 'dropzone';
import lodash from 'lodash';
console.log(lodash);
console.log(dropzone);
console.log(xlsx);
console.log(axios);
var s=document.createElement('div')
s.innerHTML='dome文件'
document.getElementById('app').appendChild(s);
引入了lodash、dropzone、xlsx、axios这4个包。
src/module/test/test.js
import echarts from 'echarts';
import xlsx from 'xlsx';
import dropzone from 'dropzone';
console.log(dropzone);
console.log(xlsx);
console.log(echarts)
var s=document.createElement('div')
s.innerHTML='test文件'
document.getElementById('app').appendChild(s);
引入了dropzone、xlsx、echarts这3个包。
app.js
import "regenerator-runtime/runtime";
import React from 'react';
import ReactDOM from 'react-dom';
import About from './src/view/about';
import Inbox from './src/view/inbox';
// import asyncComponent from './src/assets/js/AsyncComponent'
// const Inbox = asyncComponent(() => import( './src/view/inbox'));
// const About = asyncComponent(() => import( './src/view/about'));
import { BrowserRouter as Router, Switch, Redirect, Route, Link, HashRouter ,RouteChildren} from 'react-router-dom'
class App extends React.Component {
render() {
return (
<div className="shopping-list">
{this.props.children}
<ul>
<li><Link to="/about">About</Link></li>
<li><Link to="/inbox">Inbox</Link></li>
</ul>
</div>
);
}
}
class Home extends React.Component {
render() {
return (
<HashRouter>
<Switch>
<App>
<Route path="/about" component={About} />
<Route path="/inbox" component={Inbox} />
</App>
</Switch>
</HashRouter>
)
}
}
ReactDOM.render(
<Home />,
document.getElementById('app')
);
引入了react、react-dom这2个包。
拆包分析
demo.js与test.js 有使用相同的包dropzone和xlsx。 app.js 只使用了 react和react-dom。
splitChunks 进行默认配置。
optimization: {
splitChunks: {
chunks: 'all',
minSize: 30000,
maxSize: 0,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: '~',
name: true,
cacheGroups: {
vendors: {
name:'vendors',
chunks: 'all',
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
},
直接打包
npm run build
npm run server
结果
总结
说明引入的包都打包到一个js文件了,每个多页面都加载了多余的包。所以默认配置不能很好的进行多页面的拆包。
进行拆包优化配置
修改splitChunks代码
optimization: {
splitChunks: {
chunks: 'all',
minSize: 30000,
maxSize: 0,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: '~',
name: true,
cacheGroups: {
reactVendors: { //reactVendors 来匹配react相关的包
chunks: 'all',
test: /(react|react-dom|react-dom-router)/,
priority: 100,
name: 'react',
},
commonVendors: { // commonVendors 来匹配xlsx和dropzone的包
chunks: 'all',
test: /(dropzone|xlsx)/,
priority: 90,
name: 'commonMode',
},
vendors: {
name:'vendors',
chunks: 'all',
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
},
多配置了commonVendors和reactVendors这两个匹配项目。 试试 可不可以。
npm run build
所以chunks没有引入包所有需要去引入。
不同的入口文件引入不同的chunks
所以 app.js 这个入口文件需要引入 react 这个chunks。
new htmlWebpackPlugin({
filename:'index.html',
template:'./index.html',
inject:true,
chunks: ['vendors','app','react'],
minify: {
// 压缩 HTML 文件
removeComments: isPord, // 移除 HTML 中的注释
collapseWhitespace: isPord, // 删除空白符与换行符
minifyCSS: isPord // 压缩内联 css
},
})
].concat(concatHtmlWebpackPlugin())
多页面需要引入 commonMode 这个chunks。
function concatHtmlWebpackPlugin() {
var entriesHtml = help.getEntry(['./src/module/**/*.html']);
console.log(entriesHtml)
var res = [];
for (var i in entriesHtml) {
var html = entriesHtml[i];
var obj = new htmlWebpackPlugin({
filename: '.' + html.substring(html.lastIndexOf('/')),
template: html, //html模板路径
inject: true, //允许插件修改哪些内容,包括head与body
chunks: ['vendors',i,'commonMode'],//i代表入口文件的key
minify: {
// 压缩 HTML 文件
removeComments: isPord, // 移除 HTML 中的注释
collapseWhitespace: isPord, // 删除空白符与换行符
minifyCSS: isPord // 压缩内联 css
},
})
res.push(obj)
}
return res
}
配置完成后。