Webpack 4 多页面应用构建实战:ES6、Sass与插件配置详解

作者:函数茶馆

时间:2026-10-22

浏览:619

本文详细解析基于 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 的压缩,基本覆盖了前端构建中的常用功能。

项目的代码目录结构如下所示。

Webpack 与多页面应用构建概述

核心构建难点与配置详解

接下来单独介绍几个构建过程中的难点配置。

多页面打包配置

第一,多页面打包。主要使用 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 命令。

以上就是本文的全部内容,希望对各位的学习有所帮助,也欢迎大家继续支持本站。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章