webpack常用配置搭建

160 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天,点击查看活动详情

我的博客网站,学习react后写的,开源了管理系统及后台WebApi,欢迎查看交流 👉 www.weison-zhong.cn

前言

本文章仅介绍前端开发中常用的webpack的配置,基于webpack@5.73.0,不涉及webpack原理知识,若想学习原理相关的,可以看👉[万字总结] 一文吃透 Webpack 核心原理

1 初始化

  1. mkdir webpack-learn-notes
  2. cd webpack-learn-notes
  3. npm init 按提示完成即可
  4. npm install webpack webpack-cli -D 安装webpack

2 配置webpack.config.js

  • 在项目根目录下新建webpack.config.js文件及src目录,并在src下新建index.js入口文件,在里面写入简单的测试代码。
class Test {
  constructor() {
    document.write("test");
  }
}
new Test();
![image.png](https://p1-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/fd905ac36c864e50b1024eed81264504~tplv-k3u1fbpfcp-watermark.image?)
  • 控制台运行 npx webpack 打包,webpack会默认帮我们在根目录创建了dist文件夹用来保存输出文件,里面有main.js,但这段代码直接在浏览器跑是不行的,后面需要配置babel转换为es5的代码。 image.png
  • 当然,我们也可以手动配置打包入口和输出目录
    const path = require("path");
    module.exports = {
      entry: "./src/index.js", // 打包入口地址
      output: {
        path: path.join(__dirname, "dist"), // 输出文件目录
        filename: "bundle.js", // 输出文件名
      },
    };
    
  • 此时查看控制台发现有个warning警告,提醒我们配置一下配置 mode,webpack目前有以下三种模式:
    • developmen:开发模式,打包更加快速,省了代码优化步骤;
    • production:生产模式,打包比较慢,会开启 tree-shaking和压缩代码;(默认模式)
    • none:不使用任何默认优化选项 image.png
  • mode配置方式:
    • 在项目根目录下新建webpack.config.js配置:
    module.exports = {
      mode: 'development',
      ...
    };
    
    配置好重新运行npx webpack 查看已经没有警告信息了 image.png
    • 或者从cli中传递参数: webpack --mode=development

3 配置babel

  • 先安装依赖: npm install babel-loader @babel/core @babel/preset-env -D
    • babel-loader 使用 Babel 加载 ES2015+ 代码并将其转换为 ES5;
    • @babel/core Babel 编译的核心包;
    • @babel/preset-env Babel 编译的预设,可以理解为 Babel 插件的超集.
  • 根目录下新增.babelrc 配置文件
// .babelrc
{
  "presets": ["@babel/preset-env"]
}
  • 修改webpack.config.js配置
    const path = require("path");
    module.exports = {
      mode: "development", // 模式
      entry: "./src/index.js", // 打包入口地址
      output: {
        path: path.join(__dirname, "dist"), // 输出文件目录
        filename: "bundle.js", // 输出文件名
      },
      module: {
        rules: [
         {
          test: /\.(jsx|js)$/,
          use: "babel-loader",
        },
        ],
      },
    };
    
    • 配置完成后再打包发现代码已经转换为es5 image.png

4 配置html-webpack-plugin

  • 如果不配置html-webpack-plugin插件,那么我们打包完后要手动在dist目录下新建index.html并把js文件引入script标签中; image.png 此时在浏览器中即可预览到效果 image.png
  • 实际项目中,通常会配置打包文件名的哈希值配合设置浏览器缓存,这样每次打包输出的文件名都不同,而借助html-webpack-plugin插件可自动帮我们完成把打包文件插入html这项工作;
  • ,安装依赖 npm install html-webpack-plugin -D,根目录下新建public目录用来存放静态资源,并在其中新建index.html模板 image.png
  • 在webpack.config.js中配置 html-webpack-plugin
    ...
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    module.exports = {
    ...
      plugins: [
        new HtmlWebpackPlugin({
          template: path.resolve(__dirname, './public/index.html'),
          inject: 'body',
          scriptLoading: 'blocking',
        }),
      ]
    }
    
  • 我们可以先删除dist文件夹再运行npx webpack打包看看效果 image.png 可以看到已经自动生成了index.html并引入了js文件

5 配置文件名哈希值

  • 实际项目中一般都有在web服务器上配置浏览器缓存以加快页面加载和减轻服务器压力,以我自己的博客网站为例,在nginx中我给js和图片等静态资源配置了强缓存,所以配置文件名哈希值是很必要的,否则当页面有新更新时浏览器还读取了旧的缓存文件。 image.png image.png

  • 配置只需要在webpack.config.js的output属性中修改下filename即可

    module.exports = {
      ...
      output: {
        path: path.join(__dirname, "dist"), // 输出文件目录
        filename: "bundle.[contenthash:8].js",//contenthash指每个文件都有单独的hash值,文件的改动只会影响自身的hash值
      },
    
  • 重新打包即可看到效果

    image.png 但发现旧的bundle.js文件还在,所以还要配置clean-webpack-plugin插件来自动清空打包目录

6 配置clean-webpack-plugin清空打包目录

  • 安装依赖:npm install clean-webpack-plugin -D
  • 修改webpack.config.js中的plugins属性
module.exports = {
  ...
  plugins: [
    new HtmlWebpackPlugin({
      template: path.resolve(__dirname, "./public/index.html"),
      inject: "body",
      scriptLoading: "blocking",
    }),
    new CleanWebpackPlugin(), //清空打包目录
  ],
};
  • 重新打包发现dist会先清空,不会有旧的文件了

7 配置css-loader

  • 新建index.css文件并在index.js中导入

    image.png

  • 重新打包,发现控制台有报错,提示需要loader来处理css文件

    image.png

  • 安装依赖 npm install css-loader -D

  • 配置webpack.config.js

 ...
  module: {
      {
        test: /\.css$/, //匹配所有的 css 文件
        use: "css-loader", // use: 对应的 Loader 名称
      },
    ],
  },
  ...

重新打包预览发现并没有效果 image.png

因为还少了style-loader,先npm install style-loader -D 安装依赖 修改配置后重新打包

```js
...
 {
        test: /\.css$/, 
        use: ["style-loader", "css-loader"], //loadeer执行顺序是从右至左
  },
 ...
```

此时预览发现已经有效果了

image.png

8 配置less-loader

  • 安装依赖 npm install less less-loader -D
  • 修改index.css为index.less
  • 修改配置文件
    ...
     {
            test: /\.(le|c)ss$/, 
            use: ["style-loader", "css-loader", "less-loader"], 
      },
     ...
    

9 抽离并压缩css文件

  • 安装依赖 npm i css-minimizer-webpack-plugin -D
  • 修改配置文件
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
   ...
    module: {
    ...
        {
          test: /\.(le|c)ss$/,
          use: [MiniCssExtractPlugin.loader, "css-loader", "less-loader"],
        },
      ],
    },
    optimization: {
      minimizer: [new CssMinimizerPlugin()],
    },
    plugins: [
   ...
      new MiniCssExtractPlugin(),
    ],
   ...
  • 重新打包发现css文件已经单独抽离 image.png

10 安装webpack-dev-server工具实现热更新

  • 安装依赖 npm install webpack-dev-server -D
  • 修改配置文件
    module.exports = {
      ...
      plugins:[...],
      devServer: {
        port: "3000", // 默认是 8080
        hot: true,
        compress: true, // 是否启用 gzip 压缩
        open: false, // 是否自动打开浏览器
        proxy: { //配置代理
          "/api": {
            target: "http://0.0.0.0:5000",
            pathRewrite: {
              "/api": "",
            },
          },
        },
      },
      ...
    
  • 在package.json的script中添加一个命令
      "scripts": {
        "dev": "webpack serve"
      },
    
  • 控制台执行npm run dev即可启动项目且浏览器自动打开了 http://localhost:3000/ ,修改样式发现可以自动构建并实时预览效果了
  • 关于npm run xxx可看我的另一篇文章npm run xxx的执行流程

11 配置sourcemap

  • 修改index.js
    import './index.less'
    class Test {
      constructor() {
        document.write("test");
      }
    }
    new Test();
    console.log(a);
    
    控制台会报ReferenceError错误,但如果不配置sourcemap,我们很难找出出错位置 image.png
  • 修改webpack.config.js
    module.exports = {
      ...
      devtool: 'eval-cheap-module-source-map',
    };
    
    重新启动项目即可看到效果 image.png

12 配置环境

  • 在第11条中,对于生产环境一般不需要生成sourcemap,所以需要根据开发和生产等不同环境对webpack做不同的配置;
  • 首先需要修改下script脚本传递不同参数区分环境:
      "scripts": {
        "dev": "webpack serve --env development",
        "build": "webpack --env production"
      }
    
    • 又或者拆分成不同脚本,例如create-react-app脚手架搭建的react项目
      image.png
  • 修改webpack.config.js配置文件
    module.exports = function (env) {
      const isEnvDevelopment = env.development;//判断是否为开发环境
      return {
        ...
        devtool: isEnvDevelopment ? "eval-cheap-module-source-map" : false,
        ...
    };
    

13 配置copy-webpack-plugin插件复制静态资源到打包目录

  • 在public目录下新建js文件夹存放foo.js,在index.html中引入 image.png
  • 重新打包打开预览发现找不到foo.js文件,因为dist目录并没有这个文件 image.png
  • 安装依赖 npm install copy-webpack-plugin -D
  • 修改配置文件
    const CopyWebpackPlugin = require("copy-webpack-plugin");
    ...
       new CopyWebpackPlugin({
        patterns: [
          {
            from: path.resolve(__dirname, "public/static"),
            to: path.resolve(__dirname, "dist/static"),
          },
        ],
      }),
   ...
  • 运行npm run build 打包后发现已经自动将文件复制到dist目录了 image.png

14 资源加载器

  • 改造一下index.js,并在src目录下创建如下结构保存图片 image.png 此时控制台会报错 image.png
  • 修改webpack.config.js配置文件,再重新启动项目就可以了
    rules: [ 
        ...
          {
              test: /\.(png|jpg|gif|jpeg|webp|svg|eot|ttf|woff|woff2)$/,
              type: "asset",
              generator: {
                filename: "assets/[name].[hash:8].[ext]",
              },
              parser: {
                dataUrlCondition: {
                  maxSize: 10 * 1024, //超过10kb时不转换为base64
                },
              },
            },
    ]
    
    image.png

15 配置路径别名

  • 修改配置文件
     ...
     resolve: {
          // 配置别名
          alias: {
            "@": path.join(__dirname, "src"),
          },
        },
    
  • 测试效果
    import photo1 from '../src/assets/images/a.png'
    改为 ↓
    import photo1 from '@/assets/images/a.png'
    

16 添加react支持 基于react17

  • 安装依赖 npm i @babel/preset-react -D
  • 修改.babelrc 配置文件
    // .babelrc
    {
      "presets": ["@babel/preset-env", "@babel/preset-react"]
    }
    
  • 新建App.jsx组件并修改index.js文件
//App.jsx
import React from 'react'
export default function App() {
  return (
    <div>App</div>
  )
}
//index.js
import ReactDOM from "react-dom";
import React from "react";
import App from "./App.jsx";
ReactDOM.render(<App />, document.getElementById("root"));

image.png

  • 重新启动项目即可

17 添加Vue支持 基于Vue3

  • 安装依赖:
    • npm i -D vue-loader vue-template-compiler vue-style-loader
    • npm i vue -S
  • 修改webpack配置
    const { VueLoaderPlugin } = require("vue-loader/dist/index");
    //rules中增加
      {
              test: /\.vue$/,
              use: ["vue-loader"],
       },
    //plugins中增加new VueLoaderPlugin(),
    
  • 新增App.vue
<template>
  <div>
    <p class="title">{{ title }}</p>
  </div>
</template>
<script>
import { defineComponent, ref } from "vue";
export default defineComponent({
  setup() {
    const title = ref("test");
    return {
      title,
    };
  },
});
</script>
<style scoped>
.title {
  color: #000;
}
</style>
  • 修改index.js
import { createApp } from "vue";
import App from "./App.vue";

const app = createApp(App);
app.mount("#root");
  • 重启项目即可

18 webpack构建配置优化

学习中...