【webpack】基础 - HTML、CSS资源打包

197 阅读7分钟

一、深入理解Webpack配置文件

1.1 webpack配置文件 - webpack.config.js

1. 特点:

  • 简化命令的选项
  • 默认配置文件名称为webpack.config.js
  • 操作webpack大部分都在配置webpack.config.js文件
  • webpack 的配置文件是JavaScript文件,文件内导出了一个 webpack 配置的对象
  • webpack遵循 CommonJS 模块规范
  • 支持导出为多个配置
  • 支持由多种编程和数据语言编写的配置文件

2. 配置详情:

  • 配置文件:在项目根目录下创建文件webpack.config.js

  • 文件详情:webpack配置文件的详情我们可以大致按照以下几类进行分类

    • Mode - 模式
    • entry - 入口
    • output - 出口
    • module - 模块
    • 服务器 - devServer
    • 插件 - plugins
  • 打包命令配置:

    在文件 package.json 中的调试字段scripts新增值"build": "webpack",

    image.png

3. 文件详情 - Mode(模式)

  • 作用:告知webpack使用响应模式的内置优化

  • 使用

    // 打包模式配置
    mode: String, // 默认值:production。值的范围:development || production || none
    
    • development:开发环境。会将 DefinePluginprocess.env.NODE_ENV 的值设置为 development。为模块和chunk启用有效的名
    • production:生产环境。会将 DefinePluginprocess.env.NODE_ENV 的值设置为 production。为模块和chunk启用确定性的混淆名称
    • none:不适用任何默认优化选项

    通过修改mode的值,再打包,对比打包后的文件内容,我们可以清晰看到这三个值打包后的区别:

    image.png

4. 文件详情 - entry(入口)

  • 作用:入口对象是用于 webpack 查找构建 bundle 的地方。
  • 使用
    • 单个入口:

      用法:string || [string]

      module.exports = {
        entry: './src/index.js',
      };
      
      // 是以下形式的简写:
      module.exports = {
        entry: {
          main: './path/to/my/entry/file.js',
        },
      };
      

      一次注入多个依赖文件,并且将它们的依赖关系绘制在一个“chunk”中时,可以采用数组的方式:

      module.exports = {
        entry: ['./src/file_1.js', './src/file_2.js'],
        output: {
          filename: 'bundle.js',
        },
      };
      
  • 优点:适用于通过一个入口为应用程序或工具快熟设置 webpack 配置
  • 缺点:扩展或调整配置的灵活性不大

5. 文件详情 - output(出口)

  • 作用:告知 webpack 如何向硬盘写入编译文件。指定输出文件的目标路径和文件名

  • 特点

    • 只能制定一个 output 配置
  • 使用

    const { resolve } = require("path")
    module.exports = {
        output: {
            // 所有输出文件的目标路径,必须是绝对路径
            path: resolve(__dirname, 'dist'),
            // 出口文件名配置
            filename: 'main.js'
        }
    }
    

    效果如下: image.png

6. 文件详情 - modules(模块)

  • 作用:决定了如何处理项目中的 不同类型的模块
    • 天生支持的模块类型:
      • ECMAScript 模块
      • CommonJS 模块
      • AMD 模块
      • ASSets
      • WebAddembly 模块
  • 使用
    • 用法:Object
    // 模块配置
    module: {
        generator: {
            // webpack5.12.0+;在一个地方配置所有生成器的选项
        },
        parser: {
            // webpack5.12.0+;在一个地方配置所有解析器的选项
        },
        noParser: RegExp [RegExpfunction(resource) string [string], // 防止 webpack 解析那些任何与给定正则表达式相匹配的文件。
        unsafeCache: Boolean, // 缓存模块请求的解析。true=>cache 被启用;false=>cache未被启用
        rules: [
            // 配置多个模块规则(配置loader,解析器(parser)等选项)
        ],
    },
    

7. 文件详情 - devServer(服务器开发)

  • 作用:提供了代码修改后 自动编译、自动打包、自动刷新浏览器 等的功能,会将打包后的产物放入内存中,如此一来就大大的提升了 构建速度 与 访问速度,同时也不会有磁盘的 IO 开销,延长硬盘使用寿命。
  • 使用:Object

8. 文件详情 - plugins(插件)

  • 作用:解决 loader 无法实现的其他事
  • 使用
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    const webpack = require('webpack'); // 访问内置的插件
    
    module.exports = {
      plugins: [
          // ProgressPlugin: 用于自定义编译过程中的进度报告
          new webpack.ProgressPlugin(),
          // HtmlWebpackPlugin:将生成一个HTML文件,并在其中使用 script 引入一个名为 my-first-webpack.bundle.js 的 JS 文件。
          new HtmlWebpackPlugin({ template: './src/index.html' }),
      ],
    };
    

二、HTML资源打包

2.1 自动生成HTML文件和指定模板

1 自动生成HTML文件(html-webpack-plugin)

  • 定义:该插件可以生成一个HTML文件,并在HTML中加载所有打包资源,便于服务器访问

  • 安装

    npm i html-webpack-plugin -D
    

    image.png

  • 引入

    const HtmlWebpackPlugin = require('html-webpack-plugin');
    
  • 配置

    plugins: [
        new HtmlWebpackPlugin(),
    ],
    

打包后的文件多了一个index.html文件,并且内容如下:

image.png

通过浏览器我们打开该html文件,可以看到控制台内容如下:

image.png

2 指定生成HTML模板

  • 新建HTML文件:在src下新建文件index.html

    image.png

  • 配置

    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html', // 指定 HTML 模板
            filename: 'index.html', // 指定 HTML 名称
            title: 'hello webpack', // 指定 HTML title
        }),
    ]
    
  • title 使用

    // 使用ESJ语法,是JS的模板引擎
    <title><%=htmlWebpackPlugin.options.title%></title>
    

index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><%=htmlWebpackPlugin.options.title%></title>
</head>
<body>

</body>
</html>

webpack.config.js:

/**
 * webpack.config.js
*/
const { resolve } = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
    // 打包环境设置
    mode: "none",

    // 入口
    entry: "./src/index.js",

    // 出口文件配置
    output: {
        // // 所有输出文件的目标路径,必须是绝对路径
        // path: resolve(__dirname, 'dist'),
        // // 出口文件名配置
        // filename: 'main.js'
        // 所有输出文件的目标路径,必须是绝对路径
        path: resolve(__dirname, 'outputpath'),
        // 出口文件名配置
        filename: 'filename.js'
    },

    // 插件
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html', // 指定 HTML 模板
            filename: 'index.html', // 指定 HTML 名称
            title: 'hello webpack', // 指定 HTML title
        }),
    ],
}

2.2 打包多个HTML页面和压缩

  • 配置:

    // webpack.config.js
    // 插件
    plugins: [
        new HtmlWebpackPlugin({
            template: './src/index.html', // 指定 HTML 模板
            filename: 'index.html', // 指定 HTML 名称
            title: '首页', // 指定 HTML title
        }),
        new HtmlWebpackPlugin({
            template: './src/index.html', // 指定 HTML 模板
            filename: 'mine.html', // 指定 HTML 名称
            title: '我的', // 指定 HTML title
        }),
    ],
    
  • 跳转配置:

    // src/index.html
    <body>
        <h3>webpack学习</h3>
        <a href="index.html">首页</a>
        <a href="mine.html">我的</a>
    </body>
    

效果如下:

  • 打包后文件效果:

image.png

  • 打包后文件执行效果:

image.png

image.png

  • 压缩:
    • 配置:
      // 插件
      plugins: [
          new HtmlWebpackPlugin({
              template: './src/index.html', // 指定 HTML 模板
              filename: 'index.html', // 指定 HTML 名称
              title: '首页', // 指定 HTML title
              minify: {
                  collapseWhitespace: true, // 清除空格换行
                  removeComments: true, // 清除注释
              }
          }),
          new HtmlWebpackPlugin({
              template: './src/index.html', // 指定 HTML 模板
              filename: 'mine.html', // 指定 HTML 名称
              title: '我的', // 指定 HTML title
          }),
      ],
      
    • 打包后的文件对比:
      • 经过压缩有的打包文件没有换行空格等,全部一行展示:

        image.png

      • 压缩后的文件大小明显小:

        image.png

    • 打包后的文件执行对比:与没有压缩的效果一模一样,不受影响

三、CSS资源打包

3.1 剖析CSS打包的原理

  • 打包CSS的loader

    • css-loader:将css代码转化为JS代码,合并到打包后的JS文件中
    • style-loader:将包含CSS内容的JS代码,插入到html中的style标签中
  • 安装

    npm i css-loader style-loader -D
    

    image.png

  • CSS 文件引入

    // index.js
    import './css/main.css'
    

    image.png

  • webpack配置

    // 模块配置
    module: {
        rules: [
            // 配置多个模块规则(loader、解析器等选项)
            {
                // 匹配CSS文件
                test: /\.css$/i,
                // 指定加载器,加载顺序是从左到右或者从上到下
                use: ['style-loader', 'css-loader'],
            }
        ],
    },
    
  • 打包后的效果如下:CSS内容插入在html中的style标签中

    image.png

  • 不使用 style-loader 的效果:页面背景色不见了,打包的JS文件中还是有样式的设置

    use: ['css-loader']

    image.png

3.2 将CSS代码抽象成单独文件

将CSS代码抽象成单独文件 - mini-css-extract-plugin

  • 作用

    • 从JS文件中抽离出CSS代码,减少JS文件体积
    • 当JS文件比较庞大时,可以避免阻碍页面的渲染
    • 提高渲染速度
  • 安装

    npm i mini-css-extract-plugin -D
    

    image.png

  • 引入:

    // webpack.config.js
    const miniCssExtractPlugin = require("mini-css-extract-plugin")
    
  • loader配置(替换 styl-loader)

    // webpack.config.js
    module: {
        rules: [
            // 配置多个模块规则(配置loader,解析器等选项)
            {
                // 匹配CSS文件
                test: /\.css$/i,
                // 指定加载器,加载顺序是从左到右或者从上到下
                use: [miniCssExtractPlugin.loader, 'css-loader'],
            }
        ],
    },
    
  • 实例化插件

    // webpack.config.js
    plugins: [
        new miniCssExtractPlugin({
            filename: "./css/index.css", // 指定文件位置和文件名
        })
    ],
    

打包后的效果:此时我们已经在打包后的JS文件中找不到相关CSS样式了,同时输出文件夹下多了一个CSS文件夹,以及一个index.css文件,

image.png

3.3 剖析CSS预编译语言

  • CSS预编译语言的安装

    • less
    npm i less less-loader -D
    
    • sass
    npm i node-sass sass-loader -D
    
    • stylus
    npm i stylus stylus-loader -D
    

    image.png

  • 使用

    // src/index.js
    import './main.less'
    
  • webpack配置

    ['style-loader', 'css-loader', 'less-loader']
    

打包后和页面效果:

image.png

3.4 对特殊的CSS样式添加兼容前缀

  • 作用

    • 兼容各个浏览器
  • 安装

    npm i postcss-loader autoprefixer -D
    
  • 配置

    • webpack.config.js
      module: {
          rules: [
            {
              test: /.css$/i,
              // postcss-loader => 处理CSS兼容
              use: [miniCssExtractPlugin.loader, 'css-loader', 'postcss-loader'], 
            },
          ],
        },
      
    • postcss.config.js
      module.exports = {
          plugins: [require('autoprefixer')] // 添加浏览器前缀
      }
      
    • package.json
      "browserslist": [
          "last 2 version", // 兼容浏览器的最近两个版本
          "> 1%", // 全球占有率超过1%的浏览器
      ]
      

打包效果如下:

image.png

3.5 CSS压缩

optimize-css-assets-webpack-plugin

  • 作用

    • 压缩后的代码去除空格和换行
    • 文件体积更小,提高请求的速度
  • 安装

    npm i optimize-css-assets-webpack-plugin -D
    
  • 引入

    // webpack.config.js
    const optimizeCssAssetsWebpackPlugin = require("optimize-css-assets-webpack-plugin");
    
  • 配置

    // webpack.config.js
    plugins: [
        new optimizeCssAssetsWebpackPlugin()
    ]
    

效果如下:

image.png

遇到的报错

安装时报错:Conflicting peer dependency: webpack@4.47.0XXXXXXXX

  • 现象

    1725897968785.jpg

  • 原因:webpack版本过高,与需要安装的插件版本不兼容有冲突

  • 解决方案

    • 安装命令后面加上 --force--legacy-peer-deps。不一定能解决
    • 降低 webpack 版本:
      • 直接覆盖原版本:npm i webpack@4.0.4 -D
      • 卸载当前版本,再重新下载需要的版本:
        // 卸载命令
        npm uninstall webpack -g
        // 安装命令
        npm i webpack@4.0.4 -D
        

资料来源