前言
在开发类似官网这类项目时,一般不会使用框架,1是因为框架体积大且官网这类项目业务逻辑比较少,基本上是静态页面,2 是不利于SEO,所以只能自己用webpack从头搭建,正好最近公司在做新的官网,因此在这里记录一下webpack4的一些配置和优化。
1.多入口并自动生成html
entry: {
index: "./src/js/index.js", // 首页
about: "./src/js/about.js", //关于我们
},
plugins: [
// 自动清空dist目录
new CleanWebpackPlugin(),
// 设置html模板生成路径
new HtmlWebpackPlugin({
filename: 'index.html',
template: './src/views/index.html',
chunks: ['index']
}),
new HtmlWebpackPlugin({
filename: 'about.html',
template: './src/views/about.html',
chunks: ['about']
}),
],
// 编译输出配置
output: {
// js生成到dist/js,[name]表示保留原js文件名
filename: 'js/[name.[hash].js',
// 输出路径为dist
path: path.resolve(__dirname, 'dist')
}
** 注意:在打包生产环境时,需在output添加publicPath属性,否则无法解析到资源目录 **
output:{
...,
publicPath: './'
}
当页面较多时,可以使用动态加载文件的方式来引入:
const fs = require("fs");
let htmlPlugins = [];
const files = fs.readdirSync(path.resolve(__dirname, "../src/views"));
htmlPlugins = files.map((item) => {
return new HtmlWebpackPlugin({
filename: item,
template: `./src/views/${item}`,
chunks: [item.split(".")[0]],
});
});
module.exports = {
......
...htmlPlugins,
}
entry也可以用同样的方式。
2. 热更新
npm install webpack-dev-server --save-dev
添加配置:
devServer: {
contentBase: "./dist",
port: 8888,
hot: true,
},
3.编译es6
npm install babel-loader @babel/core @babel/preset-env --save-dev
npm install @babel/plugin-transform-runtime @babel/plugin-transform-modules-commonjs --save-dev
npm install @babel/runtime --save
配置如下:
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: "babel-loader",
options: {
presets: ["@babel/preset-env"],
plugins: ["@babel/plugin-transform-runtime", "@babel/plugin- transform-modules-commonjs"],
},
},
},
4.加载css和scss
安装相关依赖
npm install style-loader css-loader --save-dev
npm install sass-loader node-sass --save-dev
将CSS提取为独立的文件
npm install mini-css-extract-plugin --save-dev
添加配置:
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"],
},
{
test: /\.scss$/,
use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"]
}
]
5.打包css中的图片
安装url-loader
npm install url-loader --save-dev
增加配置:
rules: [
...,
{
test: /\.(png|svg|jpg|gif|webp)$/,
use: [
{
loader: "url-loader",
options: {
// 图片输出的实际路径(相对于dist)
outputPath: "images",
// 当小于某KB时转为base64
limit: 0,
name: "[name].[ext]",
esModule: false, //高版本url-loader需添加这个属性
},
},
],
},
]
6.加载html中的图片
安装依赖:
npm install html-loader --save-dev
添加配置:
rules:[
...,
{
test: /\.(html)$/,
use: [
{
loader: "html-loader",
options: { // 改版后配置项发生了变化,请参考GitHub
attributes: true,
minimize: true,
},
},
],
},
]
7.处理第三方库,以jQuery为例
npm install jquery --save
引入后即可使用
import $ from 'jquery'
但如果项目中多个页面使用到,每个页面都引入会很麻烦,可以使用webpack的全局引入插件:
plugins: [
...,
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery",
}),
]
之后在所有页面都能直接使用jquery而不用单独引入。
8.代码复用
开发多页面应用时经常会出现代码需要多处使用的情况,比如官网的头部和底部,而复制粘贴又太low,所以我们需要实现代码复用。 在这里使用到的是html-withimg-loader这个loader,这个loader可以代替html-loader解决html中的图片加载问题,而且支持代码复用。 安装依赖:
npm install html-withimg-loader --save-dev
添加配置:
module:{
//删除html-loader相关配置
rules:[
{
test: /\.(html)$/i,
loader: "html-withimg-loader", //解决html中使用img标签路径找不到问题
}
]
}
复用语法如下:
<div>
#include("./layout/top.html")
<!--子页面将被引入,并且子页面中的img标签同样会进行处理-->
</div>
那么就可以在页面中进行代码复用 如:index.html
<div>
#include("../component/header.html")
</div>
header.css和header.js需在使用到的页面的js文件中引入, 如:index.js
import "./header.js";
import "../css/header.scss";
需要注意的是,html-withimg-loader并不能打包音视频文件,因此html中的多媒体文件需要单独在对应js文件中引入: 如:index.js
import "../images/home/video1.mp4"; //处理视频文件
9.打包优化
9.1使用BundleAnalyzerPlugin插件打包结果可视化的插件
安装依赖:
npm install webpack-bundle-analyzer --save-dev
添加配置:
plugins:[
...,
new BundleAnalyzerPlugin({
analyzerPort: 8889,
})
]
9.2拆分模块
因为多个页面都会用到如jquery这样的第三方包,那么每个文件都会把jquery打包进去,导致体积过大,因为可以使用splitChunks来拆分模块,只打包一次:
optimization: {
splitChunks: {
cacheGroups: {
vendor: {
name: "vendor",
test: /[\\/]node_modules[\\/]/,
chunks: "all",
priority: 10, // 优先级
},
},
},
},