webpack相关配置--初级

官方文档:Loaders | webpack 中文文档 

一、5 大核心概念

1. entry(入口)

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

2. output(输出)

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

3. loader(加载器)

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

4. plugins(插件)

扩展 Webpack 的功能

5. mode(模式)

主要由两种模式:

开发模式:development

生产模式:production

Webpack基本配置

webpack.config.js

const path = require("path"); // nodejs核心模块,专门用来处理路径问题

module.exports = {
  // 入口
  entry: "./src/main.js", // 相对路径
  // 输出
  output: {
    // path: 文件输出目录,必须是绝对路径
    // path.resolve()方法返回一个绝对路径
    // __dirname 当前文件的文件夹绝对路径
    path: path.resolve(__dirname, "dist"),
    // filename: 输出文件名
    filename: "main.js",
  },
  // 加载器
  module: {
    rules: [
      // loader的配置
    ],
  },
  // 插件
  plugins: [
    // plugin的配置
  ],
  // 模式
  mode: "development",
};

1. 处理样式资源

下载包

npm i css-loader style-loader -D
  • css-loader:负责将 Css 文件编译成 Webpack 能识别的模块
  • style-loader:会动态创建一个 Style 标签,里面放置 Webpack 中 Css 模块内容
npm i less-loader -D
  • less-loader:负责将 Less 文件编译成 Css 文件
npm i sass-loader sass -D
  • sass-loader:负责将 Sass 文件编译成 css 文件
  • sasssass-loader 依赖 sass 进行编译
npm i stylus-loader -D
  • stylus-loader:负责将 Styl 文件编译成 Css 文件

 配置

const path = require("path"); // nodejs核心模块,专门用来处理路径问题

module.exports = {
  // 入口
  entry: "./src/main.js", // 相对路径
  // 输出
  output: {
    // path: 文件输出目录,必须是绝对路径
    // path.resolve()方法返回一个绝对路径
    // __dirname 当前文件的文件夹绝对路径
    path: path.resolve(__dirname, "dist"),
    // filename: 输出文件名
    filename: "main.js",
  },
  // 加载器
  module: {
    rules: [
      // loader的配置
      {
        // 用来匹配 .css 结尾的文件
        test: /\.css$/,
        // use 数组里面 Loader 执行顺序是从右到左(从上到下)
        use: [
          "style-loader", // 将js中的css通过创建style标签添加到html文件中生效
          "css-loader", // 将css资源编译成commonjs的模块到js中
        ],
      },
      {
        test: /\.less$/,
        use: [
          // 使用多个loader
          "style-loader",
          "css-loader",
          "less-loader", // 将less编译成css文件
        ],
      },
      {
        test: /\.s[ac]ss$/,
        use: [
          "style-loader",
          "css-loader",
          "sass-loader", // 将less编译成css文件
        ],
      },
      {
        test: /\.styl$/,
        use: ["style-loader", "css-loader", "stylus-loader"],
      },
    ],
  },
  // 插件
  plugins: [
    // plugin的配置
  ],
  // 模式
  mode: "development",
};

2. 处理图片资源

Webpack5 将file-loader 和 url-loader  功能内置到 Webpack 里,我们只需要简单配置即可处理图片资源

const path = require("path"); // nodejs核心模块,专门用来处理路径问题

module.exports = {
  // 入口
  entry: "./src/main.js", // 相对路径
  // 输出
  output: {
    path: path.resolve(__dirname, "dist"),
    // filename: 输出文件名
    filename: "main.js",
  },
  // 加载器
  module: {
    rules: [
      // loader的配置
      {
        test: /\.(png|jpe?g|gif|webp)$/,
        type: "asset",
        parser: {
          dataUrlCondition: {
            // 小于10kb的图片会被base64处理
            // 优点:减少请求数量  缺点:体积会更大
            maxSize: 10 * 1024,
          },
        },
      },
    ],
  },
  // 插件
  plugins: [
    // plugin的配置
  ],
  // 模式
  mode: "development",
};

 3. 修改输出资源的名称和路径

(注意:需要将上次打包生成的文件清空,再重新打包才有效果)

const path = require("path"); // nodejs核心模块,专门用来处理路径问题

module.exports = {
  // 入口
  entry: "./src/main.js", // 相对路径
  // 输出
  output: {
    path: path.resolve(__dirname, "dist"),
    // filename: 输出文件名
    filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
  },
  // 加载器
  module: {
    rules: [
      // loader的配置
      {
        test: /\.(png|jpe?g|gif|webp)$/,
        type: "asset",
        parser: {
          dataUrlCondition: {
            // 小于10kb的图片会被base64处理
            // 优点:减少请求数量  缺点:体积会更大
            maxSize: 10 * 1024,
          },
        },
        generator: {
          // 将图片文件输出到 static/images 目录中
          // 将图片文件命名 [hash:8][ext][query]
          // [hash:8]: hash值取8位
          // [ext]: 使用之前的文件扩展名
          // [query]: 添加之前的query参数
          filename: "static/images/[hash:8][ext][query]",
        },
      },
    ],
  },
  // 插件
  plugins: [
    // plugin的配置
  ],
  // 模式
  mode: "development",
};

4. 自动清空上次打包资源

const path = require("path"); // nodejs核心模块,专门用来处理路径问题

module.exports = {
  // 入口
  entry: "./src/main.js", // 相对路径
  // 输出
  output: {
    path: path.resolve(__dirname, "dist"),
    // filename: 输出文件名
    filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中

    // 自动清空上次打包的内容
    // 原理:在打包前,将path整个目录内容清空,再进行打包
    clean: true, 
  },
  // 加载器
  module: {
    rules: [
      // loader的配置
    ],
  },
  // 插件
  plugins: [
    // plugin的配置
  ],
  // 模式
  mode: "development",
};

5. 处理字体图标资源

const path = require("path"); // nodejs核心模块,专门用来处理路径问题

module.exports = {
  // 入口
  entry: "./src/main.js", // 相对路径
  // 输出
  output: {
    path: path.resolve(__dirname, "dist"),
    // filename: 输出文件名
    filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
    clean: true, // 自动将上次打包目录资源清空
  },
  // 加载器
  module: {
    rules: [
      // loader的配置
      {
        test: /\.(png|jpe?g|gif|webp)$/,
        type: "asset",
        parser: {
          dataUrlCondition: {
            // 小于10kb的图片会被base64处理
            // 优点:减少请求数量  缺点:体积会更大
            maxSize: 10 * 1024,
          },
        },
        generator: {
          filename: "static/images/[hash:8][ext][query]",
        },
      },
      {
        test: /\.(ttf|woff2?)$/,
        type: "asset/resource",  // 不会转basse64
        generator: {
          // 输出名称
          filename: "static/media/[hash:8][ext][query]",
        },
      },
    ],
  },
  // 插件
  plugins: [
    // plugin的配置
  ],
  // 模式
  mode: "development",
};

6. 处理其他资源

就是在处理字体图标资源基础上增加其他文件类型,统一处理即可

const path = require("path"); // nodejs核心模块,专门用来处理路径问题

module.exports = {
  // 入口
  entry: "./src/main.js", // 相对路径
  // 输出
  output: {
    path: path.resolve(__dirname, "dist"),
    // filename: 输出文件名
    filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
    clean: true, // 自动将上次打包目录资源清空
  },
  // 加载器
  module: {
    rules: [
      // loader的配置
      {
        test: /\.(ttf|woff2?|map4|map3|avi)$/,
        type: "asset/resource",  // 不会转basse64
        generator: {
          // 输出名称
          filename: "static/media/[hash:8][ext][query]",
        },
      },
    ],
  },
  // 插件
  plugins: [
    // plugin的配置
  ],
  // 模式
  mode: "development",
};

7. 处理 js 资源

有人可能会问,js 资源 Webpack 不能已经处理了吗,为什么我们还要处理呢?

原因是 Webpack 对 js 处理是有限的,只能编译 js 中 ES 模块化语法,不能编译其他语法

其次开发中,团队对代码格式是有严格要求的,我们不能由肉眼去检测代码格式,需要使用专业的工具来检测。

  • 针对 js 兼容性处理,我们使用 Babel 来完成
  • 针对代码格式,我们使用 Eslint 来完成

我们先完成 Eslint,检测代码格式无误后,在由 Babel 做代码兼容性处理

Eslint (plugin)

https://eslint.nodejs.cn/docs/latest

可组装的 JavaScript 和 JSX 检查工具。

这句话意思就是:它是用来检测 js 和 jsx 语法的工具,可以配置各项功能。

我们使用 Eslint,关键是写 Eslint 配置文件,里面写上各种 rules 规则,将来运行 Eslint 时就会以写的规则对代码进行检查。

1. 老版本配置

.eslintrc.js 旧配置,可以直接把 ESLint 降级回 8.x 

npm install eslint@8 --save-dev

.eslintrc.js  

module.exports = {
  // 解析选项
  parserOptions: {},
  // 具体检查规则
  rules: {},
  // 继承其他规则
  extends: [],
  // ...
};

(1) parserOptions 解析选项

parserOptions: {
  ecmaVersion: 6, // ES 语法版本
  sourceType: "module", // ES 模块化
  ecmaFeatures: { // ES 其他特性
    jsx: true // 如果是 React 项目,就需要开启 jsx 语法
  }
}

 (2) rules 具体规则

  • "off" 或 0 - 关闭规则
  • "warn" 或 1 - 开启规则,使用警告级别的错误:warn (不会导致程序退出)
  • "error" 或 2 - 开启规则,使用错误级别的错误:error (当被触发的时候,程序会退出)
rules: {
  semi: "error", // 禁止使用分号
  'array-callback-return': 'warn', // 强制数组方法的回调函数中有 return 语句,否则警告
  'default-case': [
    'warn', // 要求 switch 语句中有 default 分支,否则警告
    { commentPattern: '^no default$' } // 允许在最后注释 no default, 就不会有警告了
  ],
  eqeqeq: [
    'warn', // 强制使用 === 和 !==,否则警告
    'smart' // https://eslint.bootcss.com/docs/rules/eqeqeq#smart 除了少数情况下不会有警告
  ],
}

 (3) extends 继承

开发中一点点写 rules 规则太费劲了,所以有更好的办法,继承现有的规则。

// 例如在React项目中,我们可以这样写配置
module.exports = {
  extends: ["react-app"],
  rules: {
    // 我们的规则会覆盖掉react-app的规则
    // 所以想要修改规则直接改就是了
    eqeqeq: ["warn", "smart"],
  },
};

示例:

.eslintrc.js 旧版本

module.exports = {
  // 继承 Eslint 规则
  extends: ["eslint:recommended"],
  env: {
    node: true, // 启用node中全局变量
    browser: true, // 启用浏览器中全局变量
  },
  parserOptions: {
    ecmaVersion: 6,
    sourceType: "module",
  },
  rules: {
    "no-var": 2, // 不能使用 var 定义变量
  },
};
  • webpack.config.js
const path = require("path");
const ESLintWebpackPlugin = require("eslint-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: [
      // loader
  ]
  },
  plugins: [
    new ESLintWebpackPlugin({
      // 指定检查文件的根目录
      context: path.resolve(__dirname, "src"),
    }),
  ],
  mode: "development",
};

忽略文件

  • .eslintignore
# 忽略dist目录下所有文件
dist

2. 在 Webpack 中使用新版本

npm i eslint-webpack-plugin eslint -D
    • eslint.config.mjs
    import js from "@eslint/js";
    import globals from "globals";
    import { defineConfig, globalIgnores } from "eslint/config";
    
    export default defineConfig([
      {
        files: ["**/*.js"],
        languageOptions: {
          ecmaVersion: 6, // es6
          sourceType: "module",  // es6 module
          globals: {
            ...globals.node,   // 启用node中全局变量
            ...globals.browser,  // 启用浏览器中全局变量
          },
        },
        plugins: {},
        rules: {
          ...js.configs.recommended.rules,   // 继承 Eslint 规则
          "no-var": "error",   // 不能使用 var 定义变量
        },
      },
      globalIgnores(["dist/**"]), // 忽略文件
    ]);
    

    或者直接用指令生成

    npm init @eslint/config

    Babel (loader)

    JavaScript 编译器。

    主要用于将 ES6 语法编写的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中

    babel.config.js

    module.exports = {
      // 预设
      presets: [],
    };
    

    presets 预设

    简单理解:就是一组 Babel 插件, 扩展 Babel 功能

    • @babel/preset-env: 一个智能预设,允许您使用最新的 JavaScript。
    • @babel/preset-react:一个用来编译 React jsx 语法的预设
    • @babel/preset-typescript:一个用来编译 TypeScript 语法的预设

    在 Webpack 中使用 

    npm i babel-loader @babel/core @babel/preset-env -D
    

    babel.config.js 

    module.exports = {
      // 能够编译ES6语法
      presets: ["@babel/preset-env"],
    };
    
    • webpack.config.js
    const path = require("path"); // nodejs核心模块,专门用来处理路径问题
    const ESLintWebpackPlugin = require("eslint-webpack-plugin");
    
    module.exports = {
      // 入口
      entry: "./src/main.js", // 相对路径
      // 输出
      output: {
        path: path.resolve(__dirname, "dist"),
        // filename: 输出文件名
        filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
        clean: true, // 自动将上次打包目录资源清空
      },
      // 加载器
      module: {
        rules: [
          // loader的配置
          {
            test: /\.js$/,
            exclude: /node_modules/, // 排除node_modules代码不编译
            loader: "babel-loader",
          },
        ],
      },
      // 插件
      plugins: [
        // plugin的配置
      ],
      // 模式
      mode: "development",
    };

    8. 处理 Html 资源(plugin)

    去掉引入的 js 文件,因为 HtmlWebpackPlugin 会自动引入

    npm i html-webpack-plugin -D
    
    • webpack.config.js
    const path = require("path"); // nodejs核心模块,专门用来处理路径问题
    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: 输出文件名
        filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
        clean: true, // 自动将上次打包目录资源清空
      },
      // 加载器
      module: {
        rules: [
          // loader的配置
        ],
      },
      // 插件
      plugins: [
        // plugin的配置
        new ESLintWebpackPlugin({
          // 检测哪些文件
          context: path.resolve(__dirname, "src"),
          extensions: ["js"],
        }),
        new HtmlWebpackPlugin({
          // 模板:以 public/index.html 为模板创建文件
          // 新的html文件有两个特点:1. 内容和源文件一致 2. 自动引入打包生成的js等资源
          template: path.resolve(__dirname, "public/index.html"),
        }),
      ],
      // 模式
      mode: "development",
    };
    

    9. 开发服务器&自动化 

    每次写完代码都需要手动输入指令才能编译代码,太麻烦了,我们希望一切自动化

    npm i webpack-dev-server -D
    
    • webpack.config.js
    const path = require("path"); // nodejs核心模块,专门用来处理路径问题
    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: 输出文件名
        filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
        clean: true, // 自动将上次打包目录资源清空
      },
      // 加载器
      module: {
        rules: [
          // loader的配置
        ],
      },
      // 插件
      plugins: [
        // plugin的配置
      ],
      // 开发服务器:不会输出资源,在内存中编译打包
      devServer: {
        host: "localhost", // 启动服务器域名
        port: "3000", // 启动服务器端口号
        open: true, // 是否自动打开浏览器
      },
      // 模式
      mode: "development",
    };
    

     运行指令

    // 不再是npx webpack
    npx webpack serve
    
    

    10. 生产模式介绍

    准备两个配置文件来放不同的配置

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

    修改 webpack.dev.js

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

    const path = require("path"); // nodejs核心模块,专门用来处理路径问题
    const ESLintWebpackPlugin = require("eslint-webpack-plugin");
    const HtmlWebpackPlugin = require("html-webpack-plugin");
    
    module.exports = {
      // 入口
      entry: "./src/main.js", // 相对路径
      // 输出
      output: {
        // 开发模式没有输出
        path: undefined,
        // filename: 输出文件名
        filename: "static/js/main.js",
      },
      // 加载器
      module: {
        rules: [
          // loader的配置
        ],
      },
      // 插件
      plugins: [
        // plugin的配置
        new ESLintWebpackPlugin({
          context: path.resolve(__dirname, "../src"),
          extensions: ["js"],
        }),
        new HtmlWebpackPlugin({
          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"); // nodejs核心模块,专门用来处理路径问题
    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: 输出文件名
        filename: "static/js/main.js",
        clean: true, // 自动将上次打包目录资源清空
      },
      // 加载器
      module: {
        rules: [
          // loader的配置
        ],
      },
      // 插件
      plugins: [
        // plugin的配置
        new ESLintWebpackPlugin({
          context: path.resolve(__dirname, "../src"),
          extensions: ["js"],
        }),
        new HtmlWebpackPlugin({
          template: path.resolve(__dirname, "../public/index.html"),
        }),
      ],
      // 模式
      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

     

    11. Css 处理

    (1) 提取 Css 成单独文件

    Css 文件目前被打包到 js 文件中,当 js 文件加载时,会创建一个 style 标签来生成样式

    这样对于网站来说,会出现闪屏现象,用户体验不好

    我们应该是单独的 Css 文件,通过 link 标签加载性能才好

    npm i mini-css-extract-plugin -D
    const path = require("path"); // nodejs核心模块,专门用来处理路径问题
    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: 输出文件名
        filename: "static/js/main.js",
        clean: true, // 自动将上次打包目录资源清空
      },
      // 加载器
      module: {
        rules: [
          // loader的配置
          {
            // 用来匹配 .css 结尾的文件
            test: /\.css$/,
            // use 数组里面 Loader 执行顺序是从右到左(从上到下)
            use: [
              MiniCssExtractPlugin.loader, // 提取css成单独文件
              "css-loader", // 将css资源编译成commonjs的模块到js中
            ],
          },
          {
            test: /\.less$/,
            use: [
              // 使用多个loader
              MiniCssExtractPlugin.loader,
              "css-loader",
              "less-loader", // 将less编译成css文件
            ],
          },
          {
            test: /\.s[ac]ss$/,
            use: [
              MiniCssExtractPlugin.loader,
              "css-loader",
              "sass-loader", // 将less编译成css文件
            ],
          },
          {
            test: /\.styl$/,
            use: [MiniCssExtractPlugin.loader, "css-loader", "stylus-loader"],
          },
        ],
      },
      // 插件
      plugins: [
        // plugin的配置
    
        // 提取css成单独文件
        new MiniCssExtractPlugin({
          // 定义输出文件名和目录
          filename: "static/css/main.css",
        }),
      ],
      // 模式
      mode: "production",
    };
    

    运行指令

    npm run build

    (2) Css 兼容性处理 (postcss)

    npm i postcss-loader postcss postcss-preset-env -D
    const path = require("path"); // nodejs核心模块,专门用来处理路径问题
    const ESLintWebpackPlugin = require("eslint-webpack-plugin");
    const HtmlWebpackPlugin = require("html-webpack-plugin");
    const MiniCssExtractPlugin = require("mini-css-extract-plugin");
    
    // 用来获取处理样式的 loader
    function getStyleLoader(preProcessor) {
      return [
        MiniCssExtractPlugin.loader, // 提取css成单独文件
        "css-loader", // 将css资源编译成commonjs的模块到js中
        {
          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: 输出文件名
        filename: "static/js/main.js",
        clean: true, // 自动将上次打包目录资源清空
      },
      // 加载器
      module: {
        rules: [
          // loader的配置
          {
            // 用来匹配 .css 结尾的文件
            test: /\.css$/,
            // use 数组里面 Loader 执行顺序是从右到左(从上到下)
            use: getStyleLoader(),
          },
          {
            test: /\.less$/,
            use: getStyleLoader("less-loader"),
          },
          {
            test: /\.s[ac]ss$/,
            use: getStyleLoader("sass-loader"),
          },
          {
            test: /\.styl$/,
            use: getStyleLoader("stylus-loader"),
          },
          {
            test: /\.(png|jpe?g|gif|webp)$/,
            type: "asset",
            parser: {
              dataUrlCondition: {
                maxSize: 10 * 1024,
              },
            },
            generator: {
              filename: "static/images/[hash:8][ext][query]",
            },
          },
          {
            test: /\.(ttf|woff2?|map4|map3|avi)$/,
            type: "asset/resource",
            generator: {
              filename: "static/media/[hash:8][ext][query]",
            },
          },
          {
            test: /\.js$/,
            exclude: /node_modules/, // 排除node_modules代码不编译
            loader: "babel-loader",
          },
        ],
      },
      // 插件
      plugins: [
        // plugin的配置
      ],
      // 模式
      mode: "production",
    };
    

    package.json

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

    (3)Css 压缩

    npm i css-minimizer-webpack-plugin -D
    const path = require("path"); // nodejs核心模块,专门用来处理路径问题
    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");
    
    module.exports = {
      // 入口
      entry: "./src/main.js", // 相对路径
      // 输出
      output: {
        path: path.resolve(__dirname, "../dist"),
        // filename: 输出文件名
        filename: "static/js/main.js",
        clean: true, // 自动将上次打包目录资源清空
      },
      // 加载器
      module: {
        rules: [
          // loader的配置
        ],
      },
      // 插件
      plugins: [
        // plugin的配置
        new ESLintWebpackPlugin({
          context: path.resolve(__dirname, "../src"),
          extensions: ["js"],
        }),
        new HtmlWebpackPlugin({
          template: path.resolve(__dirname, "../public/index.html"),
        }),
        // 提取css成单独文件
        new MiniCssExtractPlugin({
          filename: "static/css/main.css",
        }),
        // css压缩
        new CssMinimizerPlugin(),
      ],
      // 模式
      mode: "production",
    };
    

    12.html 压缩

    默认生产模式已经开启了:html 压缩和 js 压缩

    不需要额外进行配置

    13. 总结

    本章节我们学会了 Webpack 基本使用,掌握了以下功能:

    1. 两种开发模式

    • 开发模式:代码能编译自动化运行
    • 生产模式:代码编译优化输出

    2. Webpack 基本功能

    • 开发模式:可以编译 ES Module 语法
    • 生产模式:可以编译 ES Module 语法,压缩 js 代码

    3. Webpack 配置文件

    5 个核心概念

    • entry
    • output
    • loader
    • plugins
    • mode

     devServer 配置

    4. Webpack 脚本指令用法

    • webpack 直接打包输出
    • webpack serve 启动开发服务器,内存编译打包没有输出

    附录:

    webpack.config.js

    const path = require("path"); // nodejs核心模块,专门用来处理路径问题
    const ESLintWebpackPlugin = require("eslint-webpack-plugin");
    const HtmlWebpackPlugin = require("html-webpack-plugin");
    
    module.exports = {
      // 入口
      entry: "./src/main.js", // 相对路径
      // 输出
      output: {
        // path: 所有文件输出目录,必须是绝对路径
        // path.resolve()方法返回一个绝对路径
        // __dirname 当前文件的文件夹绝对路径
        path: path.resolve(__dirname, "dist"),
        // filename: 输出文件名
        filename: "static/js/main.js", // 将 js 文件输出到 static/js 目录中
        clean: true, // 自动将上次打包目录资源清空
      },
      // 加载器
      module: {
        rules: [
          // loader的配置
          {
            // 用来匹配 .css 结尾的文件
            test: /\.css$/,
            // use 数组里面 Loader 执行顺序是从右到左(从上到下)
            use: [
              "style-loader", // 将js中的css通过创建style标签添加到html文件中生效
              "css-loader", // 将css资源编译成commonjs的模块到js中
            ],
          },
          {
            test: /\.less$/,
            use: [
              // 使用多个loader
              "style-loader",
              "css-loader",
              "less-loader", // 将less编译成css文件
            ],
          },
          {
            test: /\.s[ac]ss$/,
            use: [
              "style-loader",
              "css-loader",
              "sass-loader", // 将less编译成css文件
            ],
          },
          {
            test: /\.styl$/,
            use: ["style-loader", "css-loader", "stylus-loader"],
          },
          {
            test: /\.(png|jpe?g|gif|webp)$/,
            type: "asset",
            parser: {
              dataUrlCondition: {
                // 小于10kb的图片会被base64处理
                // 优点:减少请求数量  缺点:体积会更大
                maxSize: 10 * 1024,
              },
            },
            generator: {
              // 将图片文件输出到 static/images 目录中
              // 将图片文件命名 [hash:8][ext][query]
              // [hash:8]: hash值取8位
              // [ext]: 使用之前的文件扩展名
              // [query]: 添加之前的query参数
              filename: "static/images/[hash:8][ext][query]",
            },
          },
          {
            test: /\.(ttf|woff2?|map4|map3|avi)$/,
            type: "asset/resource",
            generator: {
              filename: "static/media/[hash:8][ext][query]",
            },
          },
          {
            test: /\.js$/,
            exclude: /node_modules/, // 排除node_modules代码不编译
            loader: "babel-loader",
          },
        ],
      },
      // 插件
      plugins: [
        // plugin的配置
        new ESLintWebpackPlugin({
          // 检测哪些文件
          context: path.resolve(__dirname, "src"),
          extensions: ["js"],
        }),
        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",
    };
    

     webpack.prod.js

    const path = require("path"); // nodejs核心模块,专门用来处理路径问题
    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");
    
    // 用来获取处理样式的 loader
    function getStyleLoader(preProcessor) {
      return [
        MiniCssExtractPlugin.loader, // 提取css成单独文件
        "css-loader", // 将css资源编译成commonjs的模块到js中
        {
          loader: "postcss-loader",
          options: {
            postcssOptions: {
              plugins: [
                "postcss-preset-env", // 能解决大多数样式兼容性问题
              ],
            },
          },
        },
        preProcessor,
      ].filter(Boolean);
    }
    
    module.exports = {
      // 入口
      entry: "./src/main.js", // 相对路径
      // 输出
      output: {
        // path: 所有文件输出目录
        // __dirname nodejs的变量,代表当前文件的文件夹目录
        path: path.resolve(__dirname, "../dist"),
        // filename: 输出文件名
        filename: "static/js/main.js",
        clean: true, // 自动将上次打包目录资源清空
      },
      // 加载器
      module: {
        rules: [
          // loader的配置
          {
            // 用来匹配 .css 结尾的文件
            test: /\.css$/,
            // use 数组里面 Loader 执行顺序是从右到左(从上到下)
            use: getStyleLoader(),
          },
          {
            test: /\.less$/,
            use: getStyleLoader("less-loader"),
          },
          {
            test: /\.s[ac]ss$/,
            use: getStyleLoader("sass-loader"),
          },
          {
            test: /\.styl$/,
            use: getStyleLoader("stylus-loader"),
          },
          {
            test: /\.(png|jpe?g|gif|webp)$/,
            type: "asset",
            parser: {
              dataUrlCondition: {
                // 小于10kb的图片会被base64处理
                // 优点:减少请求数量  缺点:体积会更大
                maxSize: 10 * 1024,
              },
            },
            generator: {
              // 将图片文件输出到 static/images 目录中
              // 将图片文件命名 [hash:8][ext][query]
              // [hash:8]: hash值取8位
              // [ext]: 使用之前的文件扩展名
              // [query]: 添加之前的query参数
              filename: "static/images/[hash:8][ext][query]",
            },
          },
          {
            test: /\.(ttf|woff2?|map4|map3|avi)$/,
            type: "asset/resource",
            generator: {
              filename: "static/media/[hash:8][ext][query]",
            },
          },
          {
            test: /\.js$/,
            exclude: /node_modules/, // 排除node_modules代码不编译
            loader: "babel-loader",
          },
        ],
      },
      // 插件
      plugins: [
        // plugin的配置
        new ESLintWebpackPlugin({
          // 检测哪些文件
          context: path.resolve(__dirname, "../src"),
          extensions: ["js"],
        }),
        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(),
      ],
      // 模式
      mode: "production",
    };
    

    webpack.dev.js

    const path = require("path"); // nodejs核心模块,专门用来处理路径问题
    const ESLintWebpackPlugin = require("eslint-webpack-plugin");
    const HtmlWebpackPlugin = require("html-webpack-plugin");
    
    module.exports = {
      // 入口
      entry: "./src/main.js", // 相对路径
      // 输出
      output: {
        // path: 所有文件的输出目录
        // 开发模式没有输出
        path: undefined,
        // filename: 输出文件名
        filename: "static/js/main.js",
      },
      // 加载器
      module: {
        rules: [
          // loader的配置
          {
            // 用来匹配 .css 结尾的文件
            test: /\.css$/,
            // use 数组里面 Loader 执行顺序是从右到左(从上到下)
            use: [
              "style-loader", // 将js中的css通过创建style标签添加到html文件中生效
              "css-loader", // 将css资源编译成commonjs的模块到js中
            ],
          },
          {
            test: /\.less$/,
            use: [
              // 使用多个loader
              "style-loader",
              "css-loader",
              "less-loader", // 将less编译成css文件
            ],
          },
          {
            test: /\.s[ac]ss$/,
            use: [
              "style-loader",
              "css-loader",
              "sass-loader", // 将less编译成css文件
            ],
          },
          {
            test: /\.styl$/,
            use: ["style-loader", "css-loader", "stylus-loader"],
          },
          {
            test: /\.(png|jpe?g|gif|webp)$/,
            type: "asset",
            parser: {
              dataUrlCondition: {
                // 小于10kb的图片会被base64处理
                // 优点:减少请求数量  缺点:体积会更大
                maxSize: 10 * 1024,
              },
            },
            generator: {
              // 将图片文件输出到 static/images 目录中
              // 将图片文件命名 [hash:8][ext][query]
              // [hash:8]: hash值取8位
              // [ext]: 使用之前的文件扩展名
              // [query]: 添加之前的query参数
              filename: "static/images/[hash:8][ext][query]",
            },
          },
          {
            test: /\.(ttf|woff2?|map4|map3|avi)$/,
            type: "asset/resource",
            generator: {
              filename: "static/media/[hash:8][ext][query]",
            },
          },
          {
            test: /\.js$/,
            exclude: /node_modules/, // 排除node_modules代码不编译
            loader: "babel-loader",
          },
        ],
      },
      // 插件
      plugins: [
        // plugin的配置
        new ESLintWebpackPlugin({
          // 检测哪些文件
          context: path.resolve(__dirname, "../src"),
          extensions: ["js"],
        }),
        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",
    };
    

    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值