webpack基础配置

193 阅读10分钟

前言

webpack那么多配置都是怎么用的?

通过webpack可以做哪些优化?

相信每一个前端仔都有过这些疑问,这里通过此文章由浅入深介绍webpack这款打包工具,篇幅较长,希望大家可以耐心看完。

此文章以webpack5为例讲解。

项目示例地址

webpack是什么

本质上,webpack 是一个用于现代 JavaScript 应用程序的 静态模块打包工具。当 webpack 处理应用程序时,它会在内部从一个或多个入口点构建一个 依赖图(dependency graph),然后将你项目中所需的每一个模块组合成一个或多个 bundles,它们均为静态资源,用于展示你的内容。

简单来说,webpack可以将我们项目中每个chunk(模块),经过编译打包成一个或多个bundle。

为什么要使用webpack

那么有个疑问:我们的前端项目不经过webpack打包不也是可以挂到服务器上的吗?那为什么还要多此一举呢。

举个例子:项目有3个js文件,那么浏览器就需要发送三次http请求来获取这三个文件,然后依次执行其中代码。如果其中一个文件因为网络波动而延误时间,那么整个页面的加载也会随之延误。当项目日益复杂,存在上百个js文件时,页面的加载速度会被严重阻塞。

这种情况,就需要webpack帮助我们把项目编译打包成一个或几个bundle文件,减少网络请求,提升页面加载时间!!!这只是使用webpack众多好处中的一个,更多的请继续向下看。

初始化项目

接下来开始尝试使用webpack

  • 初始化项目 yarn init
  • 安装webpack有关依赖 yarn add webpack webpack-cli
  • 新建src文件夹 并写一些简单的js文件

文件结构:

文件结构.png

// src/js/sum.js
const sum = (...args) => {
  return args.reduce((p, c) => p + c, 0);
};
export default sum;
​
// src/main.js
import sum from "./js/sum";
const res = sum(1, 2);
console.log(res);
<!-- src/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>Document</title>
  </head>
  <body>
    <h1>Webpack Demo</h1>
    <script src="./main.js"></script>
  </body>
</html>

此时打开index.html页面,发现浏览器输出如下错误:

Uncaught SyntaxError: Cannot use import statement outside a module

这是因为浏览器原生是不支持es6 module的。

解决以上问题 可以通过设置script标签type='module'

这种情况就需要webpack帮助我们进行代码转译工作啦!

项目根目录下运行npx webpack ./src/main.js --mode=development,会发现根目录下自动创建dist文件下,且其下存在main.js文件,将我们index.html中script标签src路径修改为src="../dist/main.js",再次刷新浏览器,发现浏览器成功输出3。

我们先不关注这条命令具体代表什么意思,先继续向下进行。

webpack的5大核心概念

  1. entry(入口)

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

  1. output(输出)

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

  1. loader(加载器)

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

  1. plugins(插件)

扩展 Webpack 的功能

  1. mode(模式)
  • 开发模式:development
  • 生产模式:production

再回头看npx webpack ./src/main.js --mode=development这条命令

npx webpack: 是用来运行本地安装 Webpack 包的。

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

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

写一个简单的webpack配置文件

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

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

Webpack 是基于 Node.js 运行的,所以采用 Common.js 模块化规范

运行npx webpack,发现结果同npx webpack ./src/main.js --mode=development一样

如何处理样式资源

我们此时的配置还是不能够处理css资源的,这就需要我们借助loader了。

首先安装css-loader,style-loader:yarn add css-loader style-loader

  • css-loader:负责将 Css 文件编译成 Webpack 能识别的模块
  • style-loader:会动态创建一个 Style 标签,里面放置 Webpack 中 Css 模块内容
配置:
const path = require("path");
​
module.exports = {
  entry: "./src/main.js",
  output: {
    path: path.resolve(__dirname, "dist"),
    filename: "main.js",
  },
  module: {
    rules: [
      {
        // 正则匹配以.css结尾的文件
        test: /.css$/,
        // use数组里面放置loader 执行顺序是从右向左 从下向上
        use: ["style-loader", "css-loader"],
      },
    ],
  },
  plugins: [],
  mode: "development",
};
添加代码测试
/* src/css/index.csss */
.box1 {
  width: 100px;
  height: 100px;
  background: #bfa;
}
// src/main.js
import sum from "./js/sum";
import "./css/index.css";
const res = sum(1, 2);
console.log(res);
<!-- src/index.html -->
<body>
    <h1>Webpack Demo</h1>
    <div class="box1"></div>
    <script src="../dist/main.js"></script>
</body>

运行npx webpack并打开index.html页面:

css测试.png

可以看到即使我们的index.html文件中并没有写样式,但是webpack帮助我们打包编译,将main.js中引入的css先后经过css-loaderstyle-loader最终渲染到我们的DOM中。

CSS预处理器

在现在的实际项目中,我们大都会使用诸如less,scss,sass之类的css预处理器,那么webpack如何处理css这些预处理器呢?

答案当然是借助对应的loader,例如:less-loadersass-loaderstylus-loader配置如下:

module: {
  rules: [
    {
      test: /.css$/,
      use: ["style-loader", "css-loader"],
    },
    {
      test: /.less$/,
      // loader: 'xxx' // 只能使用一个loader
      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"],
    },
  ]
}

这里就不写测试代码进行测试,大家可以自行测试

处理静态资源

在webpack5之前,处理资源模块是需要额外安装loader的:

  • raw-loader: 将文件导入为字符串
  • url-loader:将文件作为data URI内联到bundle中
  • file-loader:将文件发送到输出目录

而在webpack5中,可以直接使用资源模块类型asset module type来替代上面的loader:

  • asset/resource发送一个单独的文件并导出URL。之前通过使用file-loader实现
  • asset/inline导出一个资源的data URI。之前通过使用url-loader实现
  • asset/source导出资源的源代码。之前通过使用raw-loader实现
  • asset在导出一个 data URI 和发送一个单独的文件之间自动选择。之前通过使用 url-loader,并且配置资源体积限制实现。小于 8kb 的文件,将会视为 inline 模块类型,否则会被视为 resource 模块类型。
图片类静态资源

src文件下新建image文件下,并分别添加两个大小差异较大的图片,16kb.jpeg,426kb.png。

添加配置
module: {
  rules: [
    // xxx
    {
      test: /.(png|jpe?g|gif|webp|svg)$/,
      type: "asset",
      parser: {
        dataUrlCondition: {
          /**
            * 小于20kb的图片转base 64
            * 优点:减少请求数量
            * 缺点:体积会更大 体积较小图片可以忽略
            */
          maxSize: 20 * 1024, // 20kb
        },
      },
      generator: {
        /**
          * 输出图片名称
          * [hash:10] hash值取前10位
          * [ext] 文件扩展名
          */
        filename: "static/images/[hash:10][ext][query]",
      }
    }
  ]
}
修改代码
/* src/css/index.css */
.box1 {
  width: 100px;
  height: 100px;
  background: url("../image/16kb.jpeg");
  background-size: cover;
}
// src/scss/index.scss
.box3 {
  width: 100px;
  height: 100px;
  background: url("../image/426kb.png");
  background-size: cover;
}
运行效果

16kb_img.png

小于20kb的图片资源被打包成base 64类型

426kb_img.png

大于20kb的图片资源被打包进dist/static/images目录下

字体图标类静态资源

首先在阿里巴巴矢量图标库中添加一些字体图标到我们项目中,这个具体如何添加官网上已经有详细教程,就不在这里演示。

修改配置
module: {
  rules: [
    // xxx
    {
        test: /.(ttf|woff2?)$/,
        // 字体图标不需要转base 64 采用asset/resource方式打包输出
        type: "asset/resource",
        generator: {
          filename: "static/fonts/[hash:10][ext][query]",
        },
    },
  ]
}

自动清空上次打包内容

目前我们每次运行npx webpack,都需要手动将dist文件清空,而在webpack5中可以通过配置来实现自动清空上次打包内容。

修改配置
module.exports = {
  entry: "./src/main.js",
  output: {
    // 文件输出路径 要求绝对路径
    path: path.resolve(__dirname, "dist"),
    filename: "main.js",
    // 在打包之前 将path整个目录内容清空 再进行打包
    clean: true
  }
}

eslint配置

首先需要安装插件eslint-webpack-plugin以及eslint

运行命令yarn add eslint eslint-webpack-plugin

修改配置
// webpack.config.js
const ESLintPlugin = require("eslint-webpack-plugin");
module.exports = {
  // ...
  plugins: [
    new ESLintPlugin({
      // 指定检查文件的根目录
      context: path.resolve(__dirname, "src"),
    }),
  ],
}
添加eslint规则配置文件

配置文件有很多种写法

  • .eslintrc.*:新建文件,位于项目根目录

    • .eslintrc
    • .eslintrc.js
    • .eslintrc.json
    • 区别在于配置格式不一样
  • package.jsoneslintConfig:不需要创建文件,在原有文件基础上写

ESLint 会查找和自动读取它们,所以以上配置文件只需要存在一个即可

以.eslintrc.js配置文件为例,根目录下新建.eslintrc.js

module.exports = {
  /**
   * 自己配置规则过于麻烦
   * 可以选择继承现有的规则
   * 这里采用eslint官方提供的规则模板
   * https://eslint.bootcss.com/docs/rules/
   */
  extends: ["eslint:recommended"],
  env: {
    // 启用node中全局变量
    node: true,
    // 启用浏览器中全局变量
    browser: true,
  },
  parserOptions: {
    ecmaVersion: 6, // ES 语法版本
    sourceType: "module", // ES 模块化
  },
  rules: {
    // 不能使用var定义变量
    "no-var": 2,
  },
};
测试

修改代码使其违反eslint规则校验

// src/main.js
import sum from "./js/sum";
​
var res = sum(1, 2);
console.log(res);

运行命令npx webpack观察效果

eslint.png

打包失败 因为在main.js文件中使用var定义了变量 违反了eslint的规则

需将var修改为let 或者 const 即可打包成功

eslint即时检查

以上配置只有在打包编译的时候才会发现代码中的错误,那如果想要实时进行代码检查呢?可以在vscode中安装ESLint插件,即可不用编译就能看到错误,可以提前解决,但是此时就会对项目所有文件默认进行Eslint检查,我们dist目录下打包后文件就会报错,此时需要忽略检查dist文件

根目录下新建.eslintignore文件,作用:对一些没必要进行eslint检查的文件进行忽略

这里我只配置了dist文件下内容不需要进行检查

# 忽略dist目录下所有文件
dist

如果下载了ESLint插件发现没有效果,可以在vscode setting.json中查看"eslint.enable"配置,需要将其设置为true

babel配置

Babel 主要用于将es6高级语法转化为向后兼容的语法,以便在旧版本浏览器中可以运行js代码

首先安装插件yarn add babel-loader @babel/core @babel/preset-env

修改配置
// webpack.config.js
module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /.js$/,
        // node_modules目录下文件无需编辑
        exclude: /node_modules/,
        loader: "babel-loader",
      },
    ],
  },
}
添加babel配置文件
  • babel.config.*:新建文件,位于项目根目录

    • babel.config.js
    • babel.config.json
  • .babelrc.*:新建文件,位于项目根目录

    • .babelrc
    • .babelrc.js
    • .babelrc.json
  • package.jsonbabel:不需要创建文件,在原有文件基础上写

Babel 会查找和自动读取它们,所以以上配置文件只需要存在一个即可

根目录下创建文件 .babelrc.js

module.exports = {
  /**
   * 预设 允许我们使用最新的js语法
   * 且无需关注目标环境需要进行哪些语法转换
   */
  presets: ["@babel/preset-env"],
};

处理html文件

目前我们的src/index.html文件中是手动引入打包后生成的js文件的,不仅麻烦还有可能出现引用路径不对而报错,那么我们可以通过webpack中的HtmlWebpackPlugin插件来实现自动引入打包生成的bundle

该插件将为你生成一个 HTML5 文件, 在 body 中使用 script 标签引入你所有 webpack 生成的 bundle。

安装插件yarn add html-webpack-plugin

修改配置
// webpack.config.js
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
  // ...
  plugins: [
    new HtmlWebpackPlugin({
      /**
       * 以 src/index.html 文件为模板创建新的html文件
       * 新html文件特点: 内容和源文件一致 自动引入打包生成的js等资源
       */
      template: path.resolve(__dirname, "src/index.html"),
    }),
  ],
}

运行命令npx webpack

这将会在dist目录下生成一个新的index.html文件,并且其中自动引入main.js文件

<!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>Document</title>
  <script defer src="main.js"></script></head>
  <body>
    <h1>webpack config</h1>
    <span class="iconfont icon-gongyi"></span>
    <div class="box1"></div>
    <div class="box2"></div>
    <div class="box3"></div>
    <div class="box4"></div>
    <div class="box5"></div>
  </body>
</html>

开发服务器

当前配置 我们每次写完代码都需要手动编译 太麻烦了 可以通过webpack-dev-server实现自动化打包

yarn add webpack-dev-server安装依赖

修改配置
// webpack.config.js
module.exports = {
  // ...
  // 开发服务器:不会输出打包资源 在内存中编译打包
  devServer: {
    host: "localhost", // 启动服务器的域名
    port: "3000", // 端口号
    open: true, // 自动打开浏览器
  },
}
运行指令

npx webpack serve

生产模式

生产模式介绍

在我们开发完成代码后,需要得到打包编译后的代码进行部署上线

准备工作

一般一个项目中会存在两套webpack的配置,分别对应开发模式和生产模式 ,接下来我们修改下当前目录结构。

    ├── config (Webpack配置文件目录)
    │    ├── webpack.dev.js(开发模式配置文件)
    │    └── webpack.prod.js(生产模式配置文件)

根目录下新建config文件夹,将原webpack.config.js文件重命名为webpack.dev.js,并复制一份并重命名为webpack.prod.js

修改web pack.dev.js

文件目录变了,所以所有绝对路径需要回退一层目录才能找到对应的文件

const path = require("path");
const ESLintPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
​
module.exports = {
  entry: "./src/main.js",
  output: {
    // 开发模式没有输出 不需要指定输出路径
    path: undefined,
    filename: "main.js",
    // clean: true // 开发模式没有输出 不需要清空输出结果
  },
  module: {
    rules: [
      // loader的配置
      {
        test: /.css$/,
        /**
         * 执行顺序 从右到左(从上到下)
         * css-loader 将css资源编译成commonjs的模块到js中
         * style-loader 将js中的css通过创建style标签添加到html中生效
         * index.html文件中不会看到style标签 需要通过f12查看elements面板
         */
        use: ["style-loader", "css-loader"],
      },
      {
        test: /.less$/,
        // loader: 'xxx' // 只能使用一个loader
        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|svg)$/,
        type: "asset",
        parser: {
          dataUrlCondition: {
            /**
             * 小于20kb的图片转base 64
             * 优点:减少请求数量
             * 缺点:体积会更大 体积较小图片可以忽略
             */
            maxSize: 20 * 1024, // 20kb
          },
        },
        generator: {
          /**
           * 输出图片名称
           * [hash:10] hash值取前10位
           * [ext] 文件扩展名
           */
          filename: "static/images/[hash:10][ext][query]",
        },
      },
      {
        test: /.(ttf|woff2?)$/,
        // 字体图标不需要转base 64 采用asset/resource方式打包输出
        type: "asset/resource",
        generator: {
          filename: "static/fonts/[hash:10][ext][query]",
        },
      },
      {
        test: /.js$/,
        // node_modules目录下文件无需编辑
        exclude: /node_modules/,
        loader: "babel-loader",
      },
    ],
  },
  // 插件
  plugins: [
    new ESLintPlugin({
      // 指定检查文件的根目录 回退一层
      context: path.resolve(__dirname, "../src"),
    }),
    new HtmlWebpackPlugin({
      /**
       * 以 src/index.html 文件为模板创建新的html文件
       * 新html文件特点: 内容和源文件一致 自动引入打包生成的js等资源
       * 回退一层
       */
      template: path.resolve(__dirname, "../src/index.html"),
    }),
  ],
  // 开发服务器:不会输出打包资源 在内存中编译打包
  devServer: {
    host: "localhost",
    port: "3000",
    // 自动打开浏览器
    open: true,
  },
  mode: "development",
};

开发 模式运行指令: npx webpack serve --config ./config/webpack.dev.js

修改web pack.prod.js
const path = require("path");
const ESLintPlugin = require("eslint-webpack-plugin");
const HtmlWebpackPlugin = require("html-webpack-plugin");
​
module.exports = {
  entry: "./src/main.js",
  output: {
    path: path.resolve(__dirname, "../dist"), // 生产模式需要输出
    filename: "main.js",
    clean: true
  },
  module: {
    rules: [
      // loader的配置
      {
        test: /.css$/,
        /**
         * 执行顺序 从右到左(从上到下)
         * css-loader 将css资源编译成commonjs的模块到js中
         * style-loader 将js中的css通过创建style标签添加到html中生效
         * index.html文件中不会看到style标签 需要通过f12查看elements面板
         */
        use: ["style-loader", "css-loader"],
      },
      {
        test: /.less$/,
        // loader: 'xxx' // 只能使用一个loader
        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|svg)$/,
        type: "asset",
        parser: {
          dataUrlCondition: {
            /**
             * 小于20kb的图片转base 64
             * 优点:减少请求数量
             * 缺点:体积会更大 体积较小图片可以忽略
             */
            maxSize: 20 * 1024, // 20kb
          },
        },
        generator: {
          /**
           * 输出图片名称
           * [hash:10] hash值取前10位
           * [ext] 文件扩展名
           */
          filename: "static/images/[hash:10][ext][query]",
        },
      },
      {
        test: /.(ttf|woff2?)$/,
        // 字体图标不需要转base 64 采用asset/resource方式打包输出
        type: "asset/resource",
        generator: {
          filename: "static/fonts/[hash:10][ext][query]",
        },
      },
      {
        test: /.js$/,
        // node_modules目录下文件无需编辑
        exclude: /node_modules/,
        loader: "babel-loader",
      },
    ],
  },
  // 插件
  plugins: [
    new ESLintPlugin({
      // 指定检查文件的根目录
      context: path.resolve(__dirname, "../src"),
    }),
    new HtmlWebpackPlugin({
      /**
       * 以 src/index.html 文件为模板创建新的html文件
       * 新html文件特点: 内容和源文件一致 自动引入打包生成的js等资源
       */
      template: path.resolve(__dirname, "../src/index.html"),
    }),
  ],
  mode: "production",
};

生产模式运行指令: npx webpack --config ./config/webpack.prod.js

配置运行指令

为方便不同模式的指令,我们在package.json中scripts进行定义

"scripts": {
    "start": "yarn dev",
    "dev": "webpack serve --config ./config/webpack.dev.js",
    "build": "webpack --config ./config/webpack.prod.js"
},

开发模式:yarn start

生产模式:yarn build

CSS优化

提取CSS

可以看到我们当前的打包输出中script标签中会配置defer属性,会使得js脚本在html解析完成后才执行,而此配置中我们的css样式资源也被打包到js文件中,这就会导致页面会出现短暂的样式缺失(白屏),这种情况我们就需要对css进行单独打包,并通过link标签引入html文件(link引入的外部样式文件是异步加载的)。达到html与css并行加载的目的。

script标签中defer/async与html资源解析加载图示: script.jpeg

浏览器渲染页面过程: render.jpeg

为实现以上效果,首先需安装插件yarn add mini-css-extract-plugin

本插件会将 CSS 提取到单独的文件中,为每个包含 CSS 的 JS 文件创建一个 CSS 文件,并且支持 CSS 和 SourceMaps 的按需加载。

⚠️ 注意,如果你从 webpack 入口处导入 CSS 或者在 初始 chunk 中引入 style, mini-css-extract-plugin 则不会将这些 CSS 加载到页面中。请使用 html-webpack-plugin 自动生成 link 标签或者在创建 index.html 文件时使用 link 标签。

修改配置
// config/webpack.prod.js
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
  // xxx
  module: {
    // 替换style-loader
    rules: [
      {
        test: /.css$/,
        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"],
      },
    ],
  },
  plugins: [
    // 提取css成单独文件
    new MiniCssExtractPlugin({
      // 定义输出文件名和目录
      filename: "css/main.css",
    }),
  ]
};
观察运行结果

运行yarn build,观察输出打包文件目录

 ├── dist (Webpack打包输出文件夹)
    ├── css
    │    └── main.css
    ├── static
    │    └── fonts
    │    └── images
    ├── index.html
    ├── main.js

CSS兼容性处理

yarn add postcss-loader postcss postcss-preset-env

posts-loader 使用此loader对css增加前缀,保证浏览器兼容性

修改配置
// config/webpack.prod.js
module.exports = {
  // xxx
  module: {
    rules: [
      {
        test: /.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          "css-loader",
          {
            loader: "postcss-loader",
            options: {
              postcssOptions: {
                plugins: [
                  "postcss-preset-env", // 能解决大多数样式兼容性问题
                ]},
            },
          },
        ],
      },
    ],
  },
};

添加browserslist控制样式兼容性程度

// package.json
{
  "browserslist": ["last 2 version", "> 1%", "not dead"]
}

由于我们的配置中包含了css less scss stylus 每一个都加上posts-loader的话 代码过于冗余 这里进行函数封装

// config/webpack.prod.js
const getStyleLoaders = (loader) => {
  return [
    MiniCssExtractPlugin.loader,
    "css-loader",
    {
      loader: "postcss-loader",
      options: {
        postcssOptions: {
          plugins: [
            "postcss-preset-env", // 能解决大多数样式兼容性问题
          ],
        },
      },
    },
    loader,
  ].filter(Boolean);
};
​
module.exports = {
  // xxx
  module: {
    rules: [
      {
        test: /.css$/,
        use: getStyleLoaders(),
      },
      {
        test: /.less$/,
        use: getStyleLoaders("less-loader"),
      },
      {
        test: /.s[ac]ss$/,
        use: getStyleLoaders("sass-loader"),
      },
      {
        test: /.styl$/,
        use: getStyleLoaders("stylus-loader"),
      },
    ],
  },
};

CSS压缩

yarn add css-minimizer-webpack-plugin

这个插件使用 cssnano 优化和压缩 CSS。

就像 optimize-css-assets-webpack-plugin 一样,但在 source maps 和 assets 中使用查询字符串会更加准确,支持缓存和并发模式下运行。

修改配置
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
module.exports = {
  // xxx
  plugins: [
    // css压缩
    new CssMinimizerPlugin(),
  ]
};

总结

至此,一个基础的webpack配置就已经完成了。后续将会考虑如何通过webpack进行种种优化。