Webpack学习手册

Webpack5学习手册


介绍

Webpack是一个静态资源打包工具。它会以一个或多个文件作为打包的入口,将我们整个项目所有文件编译组合成一个或多个文件输出出去。

输出的文件就是编译好的文件,就可以在浏览器中运行了。

我们将 Webpack 输出的文件叫做bundle

Webpack本身功能是有限的:

  • 开发模式:仅能编译JS中的ES Module语法
  • 生产模式:能编译JS中的ES Module语法,还能压缩JS代码
    对于其他资源的处理,还需要通过一系列的配置。

起步

  • 创建一个空文件夹 webpack-test
    资源目录如下:
webpack_code # 项目根目录(所有指令必须在这个目录运行)
    └── src # 项目源码目录
        ├── js # js文件目录
        │   ├── count.js
        │   └── sum.js
        └── main.js # 项目主文件
  • 编辑代码

    • count.js
    export default function count(x, y) {
        return x - y;
    }
    
    • sum.js
    export default function sum(...args) {
        return args.reduce((p, c) => p + c, 0);
    }
    
    • main.js
    import count from "./js/count";
    import sum from "./js/sum";
    
    console.log(count(2, 1));
    console.log(sum(1, 2, 3, 4));
    
  • 下载依赖
    打开项目终端,运行以下指令:

    • 初始化package.json
        npm i init -y
    
    • 下载依赖
        npm i webpack webpack-cli -D
    
  • 启用Webpack

    npx webpack:运行本地安装webpack

    ./src/main.js:指定Webpack从main.js文件开始打包,不但会打包main.js,还会将其依赖也一起打包进来

    --mode=xxx:指定模式(环境)

    • 开发模式
        npx webpack ./src/main.js --mode=development
    
    • 生产模式
        npx webpack ./src/main.js --mode=production
    

    默认Webpack会将文件打包输出到dist目录下。

基本配置

5大核心概念

Webpack的配置有5大核心概念:

  1. entry(入口)

    指示Webpack从哪个文件开始打包

  2. output(输出)

    指示 Webpack打包完的文件输出到哪里去,如何命名等

  3. loader(加载器)

    webpack本身只能处理js、json等资源,其他资源需要借助 loader,Webpack 才能解析

  4. plugins(插件)

    扩展 Webpack 的功能

  5. mode(模式)
    主要由两种模式:开发模式(development)生产模式(production)

创建配置文件

在项目根目录下新建:webpack.config.js

module.exports = {
  // 入口
  entry:"",
  // 输出
  output:{},
  // 加载器
  module:{
    rules:[]
  },
  //插件
  plugins:[],
  //模式
  mode:""
}

配置文件初始化

  1. 配置文件

    // Node.js的核心模块,专门用来处理文件路径
    const path = require("path");
    module.exports = {
      // 入口
      entry:"./src/main.js",    //相对路径和绝对路径都行
      // 输出
      output:{
        // path: 文件输出目录,必须是绝对路径
        // path.resovle()方法返回一个绝对路径
        // __dirname当前文件的文件夹绝对路径
        path: path.resolve(__dirname,"dist"),
        // filename:输出文件的文件名
        filename: 'main.js'
      },
      // 加载器
      module:{
        rules:[]
      },
      //插件
      plugins:[],
      //模式
      mode:"development",//开发模式
    }
    
    
  2. 运行指令

npx webpack

开发模式

开发模式就是我们开发代码时使用的模式。

这个模式下我们主要做两件事:

编译代码,使浏览器能识别运行
开发时我们有样式资源、字体图标、图片资源、html 资源等,webpack 默认都不能处理这些资源,所以我们要加载配置来编译这些资源

代码质量检查,树立代码规范
提前检查代码的一些隐患,让代码运行时能更加健壮。

提前检查代码规范和格式,统一团队编码风格,让代码更优雅美观。

开发服务器&&自动化

为了避免每次写完代码都需要手动输入指令才能编译代码,太麻烦了,我们可以通过配置进行自动化

  • 下载包
npm i webpack-dev-server -D
  • 配置
// Node.js的核心模块,专门用来处理文件路径
const path = require("path");
module.exports = {
  // 入口
  entry:"./src/main.js",    //相对路径和绝对路径都行
  // 输出
  output:{
    // path: 文件输出目录,必须是绝对路径
    // path.resovle()方法返回一个绝对路径
    // __dirname当前文件的文件夹绝对路径
    path: path.resolve(__dirname,"dist"),
    // filename:输出文件的文件名
    filename: 'main.js'
  },
  // 加载器
  module:{
    rules:[]
  },
  //插件
  plugins:[],
  //开发服务器
  devServer:{
    host:"localhost",//启动服务器域名
    port:"3000",//启动服务器端口号
    open:true,//是否自动打开浏览器
  },
  //模式
  mode:"development",//开发模式
}
  • 运行指令
npx webpack serve

注意运行指令发生了变化

并且当你使用开发服务器时,所有代码都会在内存中编译打包,并不会输出到 dist 目录下。

处理Html资源

  • 添加Html资源

    public/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>Webpack Learning</title>
  </head>
  <body>
    <h1>Hello Webpack5</h1>
  </body>
</html>
  • 下载包
npm i html-webpack-plugin -D
  • 配置
// Node.js的核心模块,专门用来处理文件路径
const path = require("path");
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
  // 入口
  entry:"./src/main.js",    //相对路径和绝对路径都行
  // 输出
  output:{
    // path: 文件输出目录,必须是绝对路径
    // path.resovle()方法返回一个绝对路径
    // __dirname当前文件的文件夹绝对路径
    path: path.resolve(__dirname,"dist"),
    // filename:输出文件的文件名
    filename: 'main.js'
  },
  // 加载器
  module:{
    rules:[]
  },
  //插件
  plugins:[
    new HtmlWebpackPlugin({
      //以public/index.html为模板创建文件
      // 新的html文件有两个特点:1.内容和源文件一致  2.自动引入打包生成的js等资源
      template:path.resolve(__dirname,"public/index.html")
    })
  ],
  //开发服务器
  devServer:{
    host:"localhost",//启动服务器域名
    port:"3000",//启动服务器端口号
    open:true,//是否自动打开浏览器
  },
  //模式
  mode:"development",//开发模式
}
  • 运行开发服务器 npx webpack serve
    因为 HtmlWebpackPlugin 会自动引入 main.js,所以可以在控制台看到main.js的输出语句

    此处输入图片的描述

处理样式资源

Webpack 本身是不能识别样式资源的,所以我们需要借助 Loader 来帮助 Webpack 解析样式资源
我们找 Loader 都应该去官方文档中找到对应的 Loader,然后使用官方文档找不到的话,可以从社区 Github 中搜索查询 Webpack 官方 Loader 文档

  • 处理CSS资源

    1. 处理CSS资源

      • 下载包
      npm i css-loader style-loader -D
      
      

      注意:需要下载两个loader

      css-loader:负责将 Css 文件编译成 Webpack 能识别的模块
      style-loader:会动态创建一个 Style 标签,里面放置 Webpack 中 Css 模块内容

      此时样式就会以 Style 标签的形式在页面上生效

      • 配置
      // Node.js的核心模块,专门用来处理文件路径
      const path = require("path");
      const HtmlWebpackPlugin = require('html-webpack-plugin')
      module.exports = {
        // 入口
        entry:"./src/main.js",    //相对路径和绝对路径都行
        // 输出
        output:{
          // path: 文件输出目录,必须是绝对路径
          // path.resovle()方法返回一个绝对路径
          // __dirname当前文件的文件夹绝对路径
          path: path.resolve(__dirname,"dist"),
          // filename:输出文件的文件名
          filename: 'main.js'
        },
        // 加载器
        module:{
          rules:[
            {
              // 用来匹配.css结尾的文件
              test:/\.css$/,
              // use数组里面Loader执行顺序是从右到左
              use:["style-loader","css-loader"]
            }
          ]
        },
        //插件
        plugins:[
          new HtmlWebpackPlugin({
            //以public/index.html为模板创建文件
            // 新的html文件有两个特点:1.内容和源文件一致  2.自动引入打包生成的js等资源
            template:path.resolve(__dirname,"public/index.html")
          })
        ],
        //开发服务器
        devServer:{
          host:"localhost",//启动服务器域名
          port:"3000",//启动服务器端口号
          open:true,//是否自动打开浏览器
        },
        //模式
        mode:"development",//开发模式
      }
      
      
    2. 添加CSS资源

      • src/css/index.css
      .box1{
          width: 100px;
          height: 100px;
          background-color: pink;
      }
      
      
      • src/main.js
      import count from './js/count';
      import sum from "./js/sum";
      // 在入口文件引入css资源,webpack才会对其打包
      import './css/index.css'
      
      console.log(count(2,1));
      console.log(sum(1,2,3,4));
      
      
      • public/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>Webpack Learning</title>
        </head>
        <body>
          <h1>Hello Webpack5</h1>
          <!-- 准备一个使用样式的  DOM容器  -->
          <div class="box1"></div>
        </body>
      </html>
      

    此时,可以在服务器看到页面多出了一个粉红色的正方形样式
    此处输入图片的描述

  • 处理CSS预处理器资源

    有了上面处理CSS资源的经验,可以举一反三处理Sass/Scss、Less等预处理器资源了。下面以处理Sass/Scss资源为例。

    1. 处理Sass/Scss资源

      • 下载包
      npm i sass-loader sass -D
      
      

      sass-loader:负责将 Sass 文件编译成 css 文件
      sasssass-loader 依赖 sass 进行编译

      • 配置
      // 加载器
      module:{
          rules:[
              ...
            {
              //用来匹配 .sass 或 .scss结尾的文件
              test:/\.s[ac]ss$/,
              use:[ "style-loader","css-loader","sass-loader" ]
            }
          ]
      }
      
    2. 添加Sass/Scss资源

      • src/sass/index.scss
      $bgColor: blue;
      
      .box2 {
        width: 100px;
        height: 100px;
        background-color: $bgColor;
      }
      
      • src/sass/index.sass
      /* 可以省略大括号和分号 */
      .box3
        width: 100px
        height: 100px
        background-color: hotpink
      
      • src/main.js
      import count from './js/count';
      import sum from "./js/sum";
      // 在入口文件引入css资源,webpack才会对其打包
      import './css/index.css'
      import './sass/index.sass'
      import './sass/index.scss'
      
      console.log(count(2,1));
      console.log(sum(1,2,3,4));
      
      • public/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>Webpack Learning</title>
        </head>
        <body>
          <h1>Hello Webpack5</h1>
          <!-- 准备一个使用样式的  DOM容器  -->
          <div class="box1"></div>
          <div class="box2"></div>
          <div class="box3"></div>
        </body>
      </html>
      

    此时,可以在服务器看到页面多出了2个正方形样式
    此处输入图片的描述

处理图片资源

  1. 配置
  // 加载器
module:{
  rules:[
        ...
        {
          test:/\.(png|jpe?g|gif|webp)$/,
          type:'asset'
        }
    ]
},

2.使用图片资源

 // src/css/index.css
.box1 {
    width: 100px;
    height: 100px;
    background-image: url('../image/1.gif');
    background-size: cover;
  }
  
  // src/sass/index.scss
  .box2 {
    width: 100px;
    height: 100px;
    background-image: url('../image/2.jpg');
    background-size: cover;
  }

  // src/sass/index.sass
  .box3
    width: 100px
    height: 100px
    background-image: url("../image/3.jpg")
    background-size: cover

查看页面效果:

此处输入图片的描述

3.输出资源情况

如果使用命令npx webpack,查看dist目录的话,会发现多了三张图片资源,Webpack会将所有打包好的资源输出到 dist 目录下。但是在dist目录下却没有样式资源,这是因为经过style-loader的处理,样式资源打包到 main.js 里面去了,所以没有额外输出出来。

4.优化图片资源
通过配置可以将小于某个大小的图片转化成 data URI 形式(Base64 格式)

优点:减少请求数量
缺点:体积变得更大

  // 加载器
     module:{
       rules:[
         ...
         {
           test:/\.(png|jpe?g|gif|webp)$/,
           type:'asset',
           parser:{
             dataUrlCondition:{
               maxSize:10*1024 // 小于10kb的图片会被base64处理
             }
           }
         }
       ]
     },

生产模式

生产模式下主要对代码进行优化,优化主要从以下两个角度出发:
1.优化代码运行性能
2.优化代码打包速度

文件目录

修改文件目录,两个配置文件对应生产模式和开发模式

├── webpack-test (项目根目录)
    ├── config (Webpack配置文件目录)
    │    ├── webpack.dev.js(开发模式配置文件)
    │    └── webpack.prod.js(生产模式配置文件)
    ├── node_modules (下载包存放目录)
    ├── src (项目源码目录,除了html其他都在src里面)
    │    └── 略
    ├── public (项目html文件)
    │    └── index.html
    ├── .eslintrc.js(Eslint配置文件)
    ├── babel.config.js(Babel配置文件)
    └── package.json (包的依赖管理配置文件)

修改webpack.dev.js

const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  entry: "./src/main.js",
  output: {
    path: undefined, // 开发模式没有输出,不需要指定输出目录
    filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
    // clean: true, // 开发模式没有输出,不需要清空输出结果
  },
  module: {
    rules: [
      {
        // 用来匹配 .css 结尾的文件
        test: /\.css$/,
        // use 数组里面 Loader 执行顺序是从右到左
        use: ["style-loader", "css-loader"],
      },
      {
        test: /\.less$/,
        use: ["style-loader", "css-loader", "less-loader"],
      },
      {
        test: /\.s[ac]ss$/,
        use: ["style-loader", "css-loader", "sass-loader"],
      },
      {
        test: /\.styl$/,
        use: ["style-loader", "css-loader", "stylus-loader"],
      },
      {
        test: /\.(png|jpe?g|gif|webp)$/,
        type: "asset",
        parser: {
          dataUrlCondition: {
            maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
          },
        },
        generator: {
          // 将图片文件输出到 static/imgs 目录中
          // 将图片文件命名 [hash:8][ext][query]
          // [hash:8]: hash值取8位
          // [ext]: 使用之前的文件扩展名
          // [query]: 添加之前的query参数
          filename: "static/imgs/[hash:8][ext][query]",
        },
      },
      {
        test: /\.(ttf|woff2?)$/,
        type: "asset/resource",
        generator: {
          filename: "static/media/[hash:8][ext][query]",
        },
      },
      {
        test: /\.js$/,
        exclude: /node_modules/, // 排除node_modules代码不编译
        loader: "babel-loader",
      },
    ],
  },
  plugins: [
    new ESLintWebpackPlugin({
      // 指定检查文件的根目录
      context: path.resolve(__dirname, "../src"),
    }),
    new HtmlWebpackPlugin({
      // 以 public/index.html 为模板创建文件
      // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
      template: path.resolve(__dirname, "../public/index.html"),
    }),
  ],
  // 其他省略
  devServer: {
    host: "localhost", // 启动服务器域名
    port: "3000", // 启动服务器端口号
    open: true, // 是否自动打开浏览器
  },
  mode: "development",
};

运行开发模式的指令:

npx webpack serve --config ./config/webpack.dev.js

修改webpack.prod.js

const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");

module.exports = {
  entry: "./src/main.js",
  output: {
    path: path.resolve(__dirname, "../dist"), // 生产模式需要输出
    filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
    clean: true,
  },
  module: {
    rules: [
      {
        // 用来匹配 .css 结尾的文件
        test: /\.css$/,
        // use 数组里面 Loader 执行顺序是从右到左
        use: ["style-loader", "css-loader"],
      },
      {
        test: /\.less$/,
        use: ["style-loader", "css-loader", "less-loader"],
      },
      {
        test: /\.s[ac]ss$/,
        use: ["style-loader", "css-loader", "sass-loader"],
      },
      {
        test: /\.styl$/,
        use: ["style-loader", "css-loader", "stylus-loader"],
      },
      {
        test: /\.(png|jpe?g|gif|webp)$/,
        type: "asset",
        parser: {
          dataUrlCondition: {
            maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
          },
        },
        generator: {
          // 将图片文件输出到 static/imgs 目录中
          // 将图片文件命名 [hash:8][ext][query]
          // [hash:8]: hash值取8位
          // [ext]: 使用之前的文件扩展名
          // [query]: 添加之前的query参数
          filename: "static/imgs/[hash:8][ext][query]",
        },
      },
      {
        test: /\.(ttf|woff2?)$/,
        type: "asset/resource",
        generator: {
          filename: "static/media/[hash:8][ext][query]",
        },
      },
      {
        test: /\.js$/,
        exclude: /node_modules/, // 排除node_modules代码不编译
        loader: "babel-loader",
      },
    ],
  },
  plugins: [
    new ESLintWebpackPlugin({
      // 指定检查文件的根目录
      context: path.resolve(__dirname, "../src"),
    }),
    new HtmlWebpackPlugin({
      // 以 public/index.html 为模板创建文件
      // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
      template: path.resolve(__dirname, "../public/index.html"),
    }),
  ],
  // devServer: {
  //   host: "localhost", // 启动服务器域名
  //   port: "3000", // 启动服务器端口号
  //   open: true, // 是否自动打开浏览器
  // },
  mode: "production",
};

运行生产模式的指令:

npx webpack --config ./config/webpack.prod.js

配置运行指令

为了方便运行不同模式的指令,在 package.json 中 scripts 里面定义指令

// package.json
{
  // 其他省略
  "scripts": {
    "start": "npm run dev",
    "dev": "npx webpack serve --config ./config/webpack.dev.js",
    "build": "npx webpack --config ./config/webpack.prod.js"
  }
}

以后启动指令:

开发模式:npm start 或 npm run dev
生产模式:npm run build

CSS处理

提取CSS成单独文件

在之前的样式资源处理中,css文件总是被打包到js文件里,这就导致在网页中,当 js 文件加载时,会创建一个 style 标签来生成样式,性能下降,用户体验不好。css文件应该是通过link标签在网页加载,性能才好。

1.下载包

npm i mini-css-extract-plugin -D

2.配置 webpack.prod.js

const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  entry: "./src/main.js",
  output: {
    path: path.resolve(__dirname, "../dist"), // 生产模式需要输出
    filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
    clean: true,
  },
  module: {
    rules: [
      {
        // 用来匹配 .css 结尾的文件
        test: /\.css$/,
        // use 数组里面 Loader 执行顺序是从右到左
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
      {
        test: /\.less$/,
        use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"],
      },
      {
        test: /\.s[ac]ss$/,
        use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
      },
      {
        test: /\.styl$/,
        use: [MiniCssExtractPlugin.loader, "css-loader", "stylus-loader"],
      },
      {
        test: /\.(png|jpe?g|gif|webp)$/,
        type: "asset",
        parser: {
          dataUrlCondition: {
            maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
          },
        },
        generator: {
          // 将图片文件输出到 static/imgs 目录中
          // 将图片文件命名 [hash:8][ext][query]
          // [hash:8]: hash值取8位
          // [ext]: 使用之前的文件扩展名
          // [query]: 添加之前的query参数
          filename: "static/imgs/[hash:8][ext][query]",
        },
      },
      {
        test: /\.(ttf|woff2?)$/,
        type: "asset/resource",
        generator: {
          filename: "static/media/[hash:8][ext][query]",
        },
      },
      {
        test: /\.js$/,
        exclude: /node_modules/, // 排除node_modules代码不编译
        loader: "babel-loader",
      },
    ],
  },
  plugins: [
    new ESLintWebpackPlugin({
      // 指定检查文件的根目录
      context: path.resolve(__dirname, "../src"),
    }),
    new HtmlWebpackPlugin({
      // 以 public/index.html 为模板创建文件
      // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
      template: path.resolve(__dirname, "../public/index.html"),
    }),
    // 提取css成单独文件
    new MiniCssExtractPlugin({
      // 定义输出文件名和目录
      filename: "static/css/main.css",
    }),
  ],
  // devServer: {
  //   host: "localhost", // 启动服务器域名
  //   port: "3000", // 启动服务器端口号
  //   open: true, // 是否自动打开浏览器
  // },
  mode: "production",
};

3.运行指令

npm run build

CSS兼容性处理

1.下载包

npm i postcss-loader postcss postcss-preset-env -D

2.配置weback.prod.js

const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
  entry: "./src/main.js",
  output: {
    path: path.resolve(__dirname, "../dist"), // 生产模式需要输出
    filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
    clean: true,
  },
  module: {
    rules: [
      {
        // 用来匹配 .css 结尾的文件
        test: /\.css$/,
        // use 数组里面 Loader 执行顺序是从右到左
        use: [
          MiniCssExtractPlugin.loader,
          "css-loader",
          {
            loader: "postcss-loader",
            options: {
              postcssOptions: {
                plugins: [
                  "postcss-preset-env", // 能解决大多数样式兼容性问题
                ],
              },
            },
          },
        ],
      },
      {
        test: /\.less$/,
        use: [
          MiniCssExtractPlugin.loader,
          "css-loader",
          {
            loader: "postcss-loader",
            options: {
              postcssOptions: {
                plugins: [
                  "postcss-preset-env", // 能解决大多数样式兼容性问题
                ],
              },
            },
          },
          "less-loader",
        ],
      },
      {
        test: /\.s[ac]ss$/,
        use: [
          MiniCssExtractPlugin.loader,
          "css-loader",
          {
            loader: "postcss-loader",
            options: {
              postcssOptions: {
                plugins: [
                  "postcss-preset-env", // 能解决大多数样式兼容性问题
                ],
              },
            },
          },
          "sass-loader",
        ],
      },
      {
        test: /\.styl$/,
        use: [
          MiniCssExtractPlugin.loader,
          "css-loader",
          {
            loader: "postcss-loader",
            options: {
              postcssOptions: {
                plugins: [
                  "postcss-preset-env", // 能解决大多数样式兼容性问题
                ],
              },
            },
          },
          "stylus-loader",
        ],
      },
      {
        test: /\.(png|jpe?g|gif|webp)$/,
        type: "asset",
        parser: {
          dataUrlCondition: {
            maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
          },
        },
        generator: {
          // 将图片文件输出到 static/imgs 目录中
          // 将图片文件命名 [hash:8][ext][query]
          // [hash:8]: hash值取8位
          // [ext]: 使用之前的文件扩展名
          // [query]: 添加之前的query参数
          filename: "static/imgs/[hash:8][ext][query]",
        },
      },
      {
        test: /\.(ttf|woff2?)$/,
        type: "asset/resource",
        generator: {
          filename: "static/media/[hash:8][ext][query]",
        },
      },
      {
        test: /\.js$/,
        exclude: /node_modules/, // 排除node_modules代码不编译
        loader: "babel-loader",
      },
    ],
  },
  plugins: [
    new ESLintWebpackPlugin({
      // 指定检查文件的根目录
      context: path.resolve(__dirname, "../src"),
    }),
    new HtmlWebpackPlugin({
      // 以 public/index.html 为模板创建文件
      // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
      template: path.resolve(__dirname, "../public/index.html"),
    }),
    // 提取css成单独文件
    new MiniCssExtractPlugin({
      // 定义输出文件名和目录
      filename: "static/css/main.css",
    }),
  ],
  // devServer: {
  //   host: "localhost", // 启动服务器域名
  //   port: "3000", // 启动服务器端口号
  //   open: true, // 是否自动打开浏览器
  // },
  mode: "production",
};

3.控制兼容性
可以在 package.json 文件中添加 browserslist 来控制样式的兼容性做到什么程度。

{
  // 其他省略
  "browserslist": ["ie >= 8"]
}

想要知道更多的 browserslist 配置,查看browserslist 文档

以上为了测试兼容性所以设置兼容浏览器 ie8 以上。

实际开发中一般不考虑旧版本浏览器了,所以可以这样设置:

{
  // 其他省略
  "browserslist": ["last 2 version", "> 1%", "not dead"]
}

4.合并配置webpack.prod.js

const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

// 获取处理样式的Loaders
const getStyleLoaders = (preProcessor) => {
  return [
    MiniCssExtractPlugin.loader,
    "css-loader",
    {
      loader: "postcss-loader",
      options: {
        postcssOptions: {
          plugins: [
            "postcss-preset-env", // 能解决大多数样式兼容性问题
          ],
        },
      },
    },
    preProcessor,
  ].filter(Boolean);
};

module.exports = {
  entry: "./src/main.js",
  output: {
    path: path.resolve(__dirname, "../dist"), // 生产模式需要输出
    filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
    clean: true,
  },
  module: {
    rules: [
      {
        // 用来匹配 .css 结尾的文件
        test: /\.css$/,
        // use 数组里面 Loader 执行顺序是从右到左
        use: getStyleLoaders(),
      },
      {
        test: /\.less$/,
        use: getStyleLoaders("less-loader"),
      },
      {
        test: /\.s[ac]ss$/,
        use: getStyleLoaders("sass-loader"),
      },
      {
        test: /\.styl$/,
        use: getStyleLoaders("stylus-loader"),
      },
      {
        test: /\.(png|jpe?g|gif|webp)$/,
        type: "asset",
        parser: {
          dataUrlCondition: {
            maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
          },
        },
        generator: {
          // 将图片文件输出到 static/imgs 目录中
          // 将图片文件命名 [hash:8][ext][query]
          // [hash:8]: hash值取8位
          // [ext]: 使用之前的文件扩展名
          // [query]: 添加之前的query参数
          filename: "static/imgs/[hash:8][ext][query]",
        },
      },
      {
        test: /\.(ttf|woff2?)$/,
        type: "asset/resource",
        generator: {
          filename: "static/media/[hash:8][ext][query]",
        },
      },
      {
        test: /\.js$/,
        exclude: /node_modules/, // 排除node_modules代码不编译
        loader: "babel-loader",
      },
    ],
  },
  plugins: [
    new ESLintWebpackPlugin({
      // 指定检查文件的根目录
      context: path.resolve(__dirname, "../src"),
    }),
    new HtmlWebpackPlugin({
      // 以 public/index.html 为模板创建文件
      // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
      template: path.resolve(__dirname, "../public/index.html"),
    }),
    // 提取css成单独文件
    new MiniCssExtractPlugin({
      // 定义输出文件名和目录
      filename: "static/css/main.css",
    }),
  ],
  // devServer: {
  //   host: "localhost", // 启动服务器域名
  //   port: "3000", // 启动服务器端口号
  //   open: true, // 是否自动打开浏览器
  // },
  mode: "production",
};

CSS压缩

1.下载包

npm i css-minimizer-webpack-plugin -D

2.配置webpack.prod.js

const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");

// 获取处理样式的Loaders
const getStyleLoaders = (preProcessor) => {
  return [
    MiniCssExtractPlugin.loader,
    "css-loader",
    {
      loader: "postcss-loader",
      options: {
        postcssOptions: {
          plugins: [
            "postcss-preset-env", // 能解决大多数样式兼容性问题
          ],
        },
      },
    },
    preProcessor,
  ].filter(Boolean);
};

module.exports = {
  entry: "./src/main.js",
  output: {
    path: path.resolve(__dirname, "../dist"), // 生产模式需要输出
    filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
    clean: true,
  },
  module: {
    rules: [
      {
        // 用来匹配 .css 结尾的文件
        test: /\.css$/,
        // use 数组里面 Loader 执行顺序是从右到左
        use: getStyleLoaders(),
      },
      {
        test: /\.less$/,
        use: getStyleLoaders("less-loader"),
      },
      {
        test: /\.s[ac]ss$/,
        use: getStyleLoaders("sass-loader"),
      },
      {
        test: /\.styl$/,
        use: getStyleLoaders("stylus-loader"),
      },
      {
        test: /\.(png|jpe?g|gif|webp)$/,
        type: "asset",
        parser: {
          dataUrlCondition: {
            maxSize: 10 * 1024, // 小于10kb的图片会被base64处理
          },
        },
        generator: {
          // 将图片文件输出到 static/imgs 目录中
          // 将图片文件命名 [hash:8][ext][query]
          // [hash:8]: hash值取8位
          // [ext]: 使用之前的文件扩展名
          // [query]: 添加之前的query参数
          filename: "static/imgs/[hash:8][ext][query]",
        },
      },
      {
        test: /\.(ttf|woff2?)$/,
        type: "asset/resource",
        generator: {
          filename: "static/media/[hash:8][ext][query]",
        },
      },
      {
        test: /\.js$/,
        exclude: /node_modules/, // 排除node_modules代码不编译
        loader: "babel-loader",
      },
    ],
  },
  plugins: [
    new ESLintWebpackPlugin({
      // 指定检查文件的根目录
      context: path.resolve(__dirname, "../src"),
    }),
    new HtmlWebpackPlugin({
      // 以 public/index.html 为模板创建文件
      // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
      template: path.resolve(__dirname, "../public/index.html"),
    }),
    // 提取css成单独文件
    new MiniCssExtractPlugin({
      // 定义输出文件名和目录
      filename: "static/css/main.css",
    }),
    // css压缩
    new CssMinimizerPlugin(),
  ],
  // devServer: {
  //   host: "localhost", // 启动服务器域名
  //   port: "3000", // 启动服务器端口号
  //   open: true, // 是否自动打开浏览器
  // },
  mode: "production",
};

posted @ 2022-08-07 20:38  小风车吱呀转  阅读(131)  评论(0编辑  收藏  举报