webpack4 + ejs 构建多页应用
目录结构
├─build webpack配置目录
│ ├─plugins.js
│ ├─rules.js
│ ├─transfromAssets.js //简单的一个插件,处理路径问题
│ └─webpack.config.js
└─src
├─components ejs公用组件目录
├─css
├─js
├─index.ejs 模板文件
└─about.ejs
源码地址:github
使用ejs模板
- 安装 ejs-loader、html-loader
- 在 src根节点创建ejs文件,作为html的模板
- 使用html-webpack-plugin引入ejs模板
index.ejs 需要向header.ejs传入htmlWebpackPlugin,否则html-webpack-plugin配置的title可能会不起作用
<%= require(\'./components/header.ejs\')({path:\'index\',htmlWebpackPlugin}) %>
<div >
内容
</div>
<%= require(\'./components/footer.ejs\')() %>
header.ejs
<head>
<meta charset="utf-8">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
webpack plugins,因为是多个页面,所以通过for循环插入HtmlWebpackPlugin
const HtmlWebpackPlugin = require(\'html-webpack-plugin\');
const plugins = [];
...
nav.forEach(value => {
plugins.push(
new HtmlWebpackPlugin({
filename: `${value.path}.html`,
template: path.resolve(__dirname, \'../src\', `${value.path}.ejs`),
inject: true,
chunks: [\'common\', value.path],
favicon: \'./src/assets/img/favicon.ico\',
title: \'title\',
minify: {
collapseWhitespace: true
}
})
)
})
...
处理css
- 使用了less,所以需要安装loader:css-loader、less-loader
- 添加浏览器前缀,兼容不同版本浏览器,需要安装postcss-loader、autoprefixer
- 需要压缩生成的css文件,安装插件:optimize-css-assets-webpack-plugin、cssnano
- 将css分离成css文件,安装mini-css-extract-plugin
处理js
安装下babel-loader、@babel/core、@babel/preset-env,处理es6的语法。
webpack配置
plugins.js
const HtmlWebpackPlugin = require(\'html-webpack-plugin\');
const MiniCssExtractPlugin = require(\'mini-css-extract-plugin\');
const optimizeCss = require(\'optimize-css-assets-webpack-plugin\');
const TransfromAssets = require(\'./transfromAssets\');
const path = require(\'path\');
const nav = require(`../src/data.js`).nav;
const plugins = [];
nav.forEach(value => {
plugins.push(
new HtmlWebpackPlugin({
filename: `${value.path}.html`,
template: path.resolve(__dirname, \'../src\', `${value.path}.ejs`),
inject: true,
chunks: [\'common\', value.path],
favicon: \'./src/assets/img/favicon.ico\',
title: \'title\',
minify: {
collapseWhitespace: true
}
})
)
})
const otherPlugins = [
new MiniCssExtractPlugin({
filename: \'[name].[hash:8].css\',
chunkFilename: \'[id].css\',
}),
new optimizeCss({
assetNameRegExp: /\.css$/g,
cssProcessor: require(\'cssnano\'),
cssProcessorOptions: {
discardComments: {
removeAll: true
}
},
canPrint: true
}),
new TransfromAssets()
];
plugins.splice(nav.length, 0, ...otherPlugins);
module.exports = plugins;
rules.js
const MiniCssExtractPlugin = require(\'mini-css-extract-plugin\');
module.exports = [{
test: /\.(c|le)ss$/,
use: [
MiniCssExtractPlugin.loader,
\'css-loader\',
{
loader: "postcss-loader",
options: {
plugins: [
require("autoprefixer")
]
}
},
\'less-loader\'
]
},
{
test: /\.js$/, //js文件加载器
exclude: /node_modules/,
use: {
loader: \'babel-loader\',
options: {
presets: [\'@babel/preset-env\']
}
}
},
{
test: /\.html$/,
use: [{
loader: \'html-loader\',
options: {
interpolate: true,
minimize: false
}
}]
}, {
test: /\.ejs/,
use: [\'ejs-loader\'],
}
]
transfromAssets.js 一个插件,作用:
- 将common.js删掉(common.js引入了公用的css,css有用但js无用所以就删啦)
- 将js、css存放至单独的目录,并将html里路径指向正确的路径
function TransfromAssets(options) {};//也可以是一个类
TransfromAssets.prototype.apply = function(compiler) {
compiler.plugin(\'emit\', function(compilation, callback) {
for (var filename in compilation.assets) {
if (/common.*js$/.test(filename)) {
delete compilation.assets[filename];
continue;
}
if (/.*[js|css]$/.test(filename)) {
let type = /.*js$/.test(filename) ? \'js\' : \'css\';
let source = compilation.assets[filename].source();
let size = compilation.assets[filename].size();
compilation.assets[`${type}/${filename}`] = {
source: () => source,
size: () => size
}
delete compilation.assets[filename];
}
if (/html$/.test(filename)) {
let source = compilation.assets[filename].source();
source = source.replace(/\<script.*?<\/script>/ig, value => ~value.indexOf(\'common\') ? \'\' : value);
source = source.replace(/href=\"\S+?.css\"/ig, value => value.slice(0, 6) + \'css/\' + value.slice(6));
source = source.replace(/src=\".*?.js\"/ig, value => value.slice(0, 5) + \'js/\' + value.slice(5));
compilation.assets[filename].source = () => source;
}
}
callback();
})
};
module.exports = TransfromAssets;
webpack.config.js
const path = require(\'path\');
const plugins = require(\'./plugins\');
const rules = require(\'./rules\');
module.exports = {
entry: {
common: \'@src/js/common.js\',
index: \'@src/js/index.js\',
detail: \'@src/js/list.js\',
},
output: {
path: path.resolve(__dirname, \'../dist/\'),
filename: "[name].[hash:8].js"
},
devServer: {
inline: true,
historyApiFallback: true,
},
resolve: {
alias: {
\'@\': path.join(__dirname, \'..\'),
\'@src\': path.join(__dirname, \'..\', \'src\')
}
},
module: {
rules
},
plugins
}