Webpack 4 多页面应用构建实战:ES6、Sass与插件配置详解
本文详细解析基于 Webpack 4 搭建多页面应用的全流程。涵盖 ES6 转译、Sass 编译、CSS 与 JS 独立打包及压缩配置。重点介绍 html-webpack-plugin、extract-text-webpack-plugin、babel-loader 及 uglifyjs 等核心插件的使用方法与常见报错解决方案,提供完整的配置文件参考。
Webpack 与多页面应用构建概述
与早期的 Gulp 非模块化打包方式不同,Webpack 是一种基于模块化的打包工具。关于两者的具体优劣对比此处不再赘述,读者可自行查阅相关资料。
本文旨在分享在实际项目中使用 Webpack 过程中涉及的插件、Loader 配置,以及遇到的各类问题和对应的解决思路,文末将提供完整的示例代码。
本项目利用 Webpack 对 CSS、SCSS、JS、图片文件、jQuery、第三方插件及字体图标进行打包,同时处理 ES6 语法转换,并实现 HTML、JS 和 CSS 的压缩,基本覆盖了前端构建中的常用功能。
项目的代码目录结构如下所示。

核心构建难点与配置详解
接下来单独介绍几个构建过程中的难点配置。
多页面打包配置
第一,多页面打包。主要使用 html-webpack-plugin 和 html-loader。每个页面对应一个入口文件,因此需要编写相应数量的模板文件。如果页面数量较多,建议采用遍历方式自动生成配置。
//引入路径插件
const path = require('path');
//引入导出html插件
const HtmlWebpackPlugin = require('html-webpack-plugin');
const config = {
//入口
entry:{
home:'./pages/lawSearchHomepage.js',
list:'./pages/lawSearchList.js'
},
//出口
output:{
filename: '[name].bundle.js',
path: path.resolve(__dirname,'build')
},
//插件
plugins: [
//html单独导出插件——首页
new HtmlWebpackPlugin({
filename:'lawSearchHomepage.html',//输出后的文件名称
template:'./pages/lawSearchHomepage.html',//模版页面路径
favicon:'./pages/images/favicon.ico',//页签图标
chunks:['home'],//需要引入的js文件名称
inject: true,
hash:true,//哈希值
minify: {//压缩
removeComments: true,
collapseWhitespace: true
}
}),
//html单独导出插件——列表页
new HtmlWebpackPlugin({
filename:'lawSearchList.html',
template:'./pages/lawSearchList.html',
favicon:'./pages/images/favicon.ico',
chunks:['list'],
inject: true,
hash:true,
minify: {
removeComments: true,
collapseWhitespace: true
}
})
]
}
module.exports = config;
CSS 单独打包与提取
第二,CSS 单独打包。使用的插件包括 extract-text-webpack-plugin,Loader 包含 style-loader、css-loader 和 sass-loader(以及 node-sass)。由于每个页面需引入对应的样式文件,在 JS 入口文件中通过 require('./lawSearchHomepage.scss') 引入相应的 SCSS 文件。打包后,CSS 文件会被单独提取,并通过 link 标签引入 HTML 中。
//引入导出css插件
const ExtractTextPlugin = require('extract-text-webpack-plugin');
//loader
{//CSS
test:/\.css/,
use:ExtractTextPlugin.extract({
use:['css-loader']
})
},
{//Sass
test:/\.scss/,
use:ExtractTextPlugin.extract({
fallback:"style-loader",
use:['css-loader','sass-loader']
},)
}
//plugins
//将css单独打包插件
new ExtractTextPlugin({
filename:"[name].css",//制定编译后的文件名称
allChunks:true,//把分割的块分别打包
}),
ES6 语法转换处理
第三,ES6 语法处理。需安装 babel、babel-loader@7(因后续压缩 JS 时其他版本会报错)、babel-core 以及 babel-preset-es2015(同样为了解决压缩 JS 时的兼容性问题)。
//loader
{//ES6
test:/\.js$/,
loader:'babel-loader',
// exclude:__dirname+'node_modules',//不对这个进行babel转换,这里边已经打包好,这样能减少打包时间
// include:__dirname+'src'这里的src是你要编译的js文件的目录,
exclude:path.resolve(__dirname,'node_modules'),
include:path.resolve(__dirname,'pages'),
query:{//若在package.json中定义了这个presets,则这边可以删掉
presets:['es2015']
}
},
jQuery 暴露处理
第四,jQuery 处理。需安装 expose-loader 插件。
第一种方法是在 JS 文件中通过 require('expose-loader?$!jquery') 引入 jQuery。
第二种方法是通过配置 Loader 实现。
//loader
{//Jquery
test: require.resolve('jquery'),
use: [{
loader: 'expose-loader',
options: 'jQuery'
},{
loader: 'expose-loader',
options: '$'
}]
},
CSS 与 JS 压缩优化
第五,CSS 压缩。使用 optimize-css-assets-webpack-plugin 插件,并需安装 cssnano。
//引入压缩css的插件
const optimizeCss = require('optimize-css-assets-webpack-plugin');
//引入cssnano插件
const cssnano = require('cssnano');
//plugins
plugins:[
new optimizeCss({
assetNameRegExp: /\.style\.css$/g,
cssProcessor: cssnano,
cssProcessorOptions: { discardComments: { removeAll:
true } },
canPrint: true
}),
],
//压缩优化css,不写这个css还是没压缩,不知道为啥
optimization: {
// minimize: true,
minimizer: [new optimizeCss({})]
},
第六,JS 压缩。通常情况下,JS 默认处于压缩状态,但在执行 CSS 压缩后,JS 可能不再保持压缩状态。因此,建议单独处理 JS 压缩,以提升编译效率。
使用的插件是 uglifyjs-webpack-plugin。
//引入js压缩插件
const uglifyjs = require('uglifyjs-webpack-plugin');
//plugins
new uglifyJs()
以下是 package.json 中安装的相关插件列表。
"devDependencies": {
"babel": "^6.23.0",
"babel-core": "^6.26.3",
"babel-loader": "^7.1.5",
"babel-preset-es2015": "^6.24.1",
"clean-webpack-plugin": "^0.1.19",
"css-loader": "^1.0.0",
"cssnano": "^4.1.7",
"expose-loader": "^0.7.5",
"extract-text-webpack-plugin": "^4.0.0-beta.0",
"file-loader": "^2.0.0",
"font-awesome-webpack": "^0.0.5-beta.2",
"html-loader": "^0.5.5",
"html-webpack-plugin": "^3.2.0",
"jquery": "^3.3.1",
"node-sass": "^4.9.4",
"optimize-css-assets-webpack-plugin": "^5.0.1",
"postcss-loader": "^3.0.0",
"sass-loader": "^7.1.0",
"style-loader": "^0.23.1",
"typeahead.js": "^0.11.1",
"uglifyjs-webpack-plugin": "^2.0.1",
"url-loader": "^1.1.2",
"webpack": "^4.23.1",
"webpack-cli": "^3.1.2",
"webpack-dev-server": "^3.1.10"
}
以下是 webpack.config.js 中的完整配置代码。
//引入路径插件
const path = require('path');
//引入导出html插件
const HtmlWebpackPlugin = require('html-webpack-plugin');
//引入清除插件
const CleanWebpackPlugin = require('clean-webpack-plugin');
//引入导出css插件
const ExtractTextPlugin = require('extract-text-webpack-plugin');
//引入webpack
const webpack = require('webpack');
//引入压缩css的插件
const optimizeCss = require('optimize-css-assets-webpack-plugin');
//引入cssnano插件
const cssnano = require('cssnano');
//引入js压缩插件
const uglifyjs = require('uglifyjs-webpack-plugin');
//webpack配置内容
const config = {
//入口
entry:{
home:'./pages/lawSearchHomepage.js',
list:'./pages/lawSearchList.js'
},
//便于调试
devtool:'inline-source-map',
//服务
devServer:{
contentBase:'./build/lawSearchHomepage.html'
},
//loader模块
module:{
rules: [
{//ES6
test:/\.js$/,
loader:'babel-loader',
// exclude:__dirname+'node_modules',//不对这个进行babel转换,这里边已经打包好,这样能减少打包时间
// include:__dirname+'src'这里的src是你要编译的js文件的目录,
exclude:path.resolve(__dirname,'node_modules'),
include:path.resolve(__dirname,'pages'),
query:{//若在package.json中定义了这个presets,则这边可以删掉
presets:['es2015']
}
},
{//Jquery
test: require.resolve('jquery'),
use: [{
loader: 'expose-loader',
options: 'jQuery'
},{
loader: 'expose-loader',
options: '$'
}]
},
{//CSS
test:/\.css/,
use:ExtractTextPlugin.extract({
use:['css-loader']
})
},
{//Sass
test:/\.scss/,
use:ExtractTextPlugin.extract({
fallback:"style-loader",
use:['css-loader','sass-loader']
},)
},
{//处理模块html
test: /\.html$/,
use: 'html-loader'
},
{//图片
test: /\.(jpg|png|gif)$/,
use: {
loader: 'file-loader',
options: {
outputPath: 'images'
}
}
},
//字体图标
{
test: /\.(eot|svg|ttf|woff|woff2)\w*/,
loader: 'file-loader'
}
]
},
//插件
plugins: [
//清空build文件下的多余文件
new CleanWebpackPlugin(['build']),
//将css单独打包插件
new ExtractTextPlugin({
filename:"[name].css",//制定编译后的文件名称
allChunks:true,//把分割的块分别打包
}),
//html单独导出插件——首页
new HtmlWebpackPlugin({
filename:'lawSearchHomepage.html',//输出后的文件名称
template:'./pages/lawSearchHomepage.html',//模版页面路径
favicon:'./pages/images/favicon.ico',//页签图标
chunks:['home'],//需要引入的js文件名称
inject: true,
hash:true,//哈希值
minify: {//压缩
removeComments: true,
collapseWhitespace: true
}
}),
//html单独导出插件——列表页
new HtmlWebpackPlugin({
filename:'lawSearchList.html',
template:'./pages/lawSearchList.html',
favicon:'./pages/images/favicon.ico',
chunks:['list'],
inject: true,
hash:true,
minify: {
removeComments: true,
collapseWhitespace: true
}
}),
//压缩css
new optimizeCss({
assetNameRegExp: /\.style\.css$/g,
cssProcessor: cssnano,
cssProcessorOptions: { discardComments: { removeAll: true } },
canPrint: true
}),
//压缩js
new uglifyjs()
],
//压缩优化css
optimization: {
// minimize: true,
minimizer: [new optimizeCss({})]
},
//出口
output:{
filename: '[name].bundle.js',
path: path.resolve(__dirname,'build')
}
}
module.exports = config;
如果在打包过程中出现模块未定义的错误,可以尝试重新安装相关依赖。如果问题依旧,建议直接删除 node_modules 文件夹,然后重新执行 npm install 命令。
以上就是本文的全部内容,希望对各位的学习有所帮助,也欢迎大家继续支持本站。
Object.assign合并JS对象的用法与注意事项
2026-11-05 17:56:08
JS大数值转字符串出现科学计数法怎么办
2026-11-05 17:09:21
JS split切割后出现空字符串怎么过滤
2026-11-05 16:00:30
在 React 或 Vue 项目中封装使用 JS 节流防抖
2026-11-05 15:27:29
JavaScript中怎么将带小数的字符串转为整数?
2026-11-05 14:32:38








