Webpack 常用配置

在上一篇 Webpack 快速上手中,我们对 Webpack 已经有了一个大概的了解,现在我们开始了解 Webpack 的配置。

webpack.config.js

const path = require('path');
// 引入 html-webpack-plugin
const HtmlWebpackPlugin = require('html-webpack-plugin')
// 引入 clean-webpack-plugin
const { CleanWebpackPlugin } = require('clean-webpack-plugin')

const time = new Date().getTime()

module.exports = {
    // 入口
    // entry: './src/index.js',
    entry: {
        index: './src/index.js',
        print: './src/print.js',
        another: './src/another_module.js'
    },

    devServer: {
        contentBase: './dist',  // 资源位置
        host: 'localhost',  // 服务器地址,如果需要在其他 PC 上访问,则将 'localhost' 改为 '0.0.0.0'
        port: '8080',
        hot: true  // 热加载
    },

    devtool: 'eval-cheap-module-source-map',  // source-map 模式

    // 插件
    plugins: [
        // 清理 ./dist 目录无用的文件
        new CleanWebpackPlugin(),
        // new webpack.HotModuleReplacementPlugin(),
        // 生成 html 文档,并自动引入「输出」文档
        new HtmlWebpackPlugin({
            title: '管理输出'
        })
    ],

    // 输出
    output: {
        // filename: 'main.js',
        filename: '[name].bundle.' + time + '.js',  // 输出文件名格式
        path: path.resolve(__dirname, 'dist')  // 输出文件位置
    },

    // 代码分离,将重复引用的代码分离出来
    optimization: {
        splitChunks: {
            chunks: 'all'
        }
    },

    // 模块
    module: {
        rules: [
            {
                // 样式加载模块
                test: /\.css$/i,
                use: ['style-loader', 'css-loader']
            },
            {
                // 图像加载模块
                test: /\.(png|svg|jpg|jpeg|gif)$/i,
                type: 'asset/resource'
            },
            {
                // 字体加载模块
                test: /\.(woff|woff2|eot|ttf|otf)$/i,
                type: 'asset/resource'
            },
            /*********** 数据加载模块 >>> ************/
            {
                // csv 加载模块
                test: /\.(csv|tsv)$/i,
                use: ['csv-loader']
            },
            {
                // xml 加载模块
                test: /\.xml$/i,
                use: ['xml-loader']
            }
            // json 加载模块:因 nodejs 默认支持 JSON 加载,所以无需再安装第三方模块
            /*********** <<< 数据加载模块 ************/
            , {
                // babel 加载模块
                test: /\.js$/,
                // exclude: /(node_mod)/
                loader: 'babel-loader',
                // include: [resolve('src'), resolve('node_modules/webpack-dev-server/client')]
                // use: {
                //   loader: 'babel-loader',
                //   options: {
                //     presets: ['@babel/preset-env']
                //   }
                // }
            }
        ]
    }
}

对应的 package.json

{
  "name": "webpack-test",
  "version": "1.0.0",
  "description": "",
  "private": true,
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "_start": "webpack serve --open firefox",
    "start": "webpack serve --inline --progress",
    "build": "webpack"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/cli": "^7.12.10",
    "@babel/core": "^7.12.10",
    "@babel/plugin-transform-runtime": "^7.12.10",
    "@babel/preset-env": "^7.12.11",
    "babel-loader": "^8.2.2",
    "clean-webpack-plugin": "^3.0.0",
    "css-loader": "^5.0.1",
    "csv-loader": "^3.0.3",
    "html-webpack-plugin": "^4.5.0",
    "style-loader": "^2.0.0",
    "webpack": "^5.4.0",
    "webpack-cli": "^4.2.0",
    "webpack-dev-server": "^3.11.0",
    "xml-loader": "^1.2.1"
  },
  "dependencies": {
    "@babel/polyfill": "^7.12.1",
    "lodash": "^4.17.20"
  },
  "browserslist": [
    "> 1%",
    "last 2 versions",
    "not ie <= 8"
  ]
}

分步讲解

  1. 入口entry
    在此我们可以看到,entry由单条更改为了对象方式,也就是说,我们的入口不仅仅可以只有一个,更是可以拥有多个入口。通过上一篇文章的学习,我们知道 webpack 可以打包使用了的资源,而entry提供了一个打包的入口,通过这个入口,就可以将入口文件里面所有相关的资源(递归搜索)打包在一起。

  2. 开发模式下的小服务器 devServer
    webpack-dev-server 提供了一个简单的 web 服务器,并且能够实时重新加载(live reloading)。

    执行命令安装 webpack-dev-server

npm install webpack-dev-server -D --registry=https://registry.npm.taobao.org

进行如上配置之后,可以在 package.json 中增加脚本启动方式 start

{
  "name": "webpack_test",
  "version": "1.0.0",
  "description": "",
  "private": true,
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "webpack serve --inline --progress",
    "build": "webpack"
  },
  "keywords": [],
  "...": ...
}

然后在命令行中执行如下命令启动服务器

npm start

此处仅为示例,更多配置请参考 webpack-dev-server

  1. 开发工具devtool
    此选项控制是否生成,以及如何生成 source map。

    我们打包过后的代码和我们自己写的源码是不一样的,如果没有 source map ,那么在开发过程中调试程序的时候,代码报错时,我们无法将错误准确的定位到我们的源码中。

    有关详细信息请参考 Devtool

  2. 插件 plugins
    plugins 选项用于以各种方式自定义 webpack 构建过程。webpack 附带了各种内置插件,可以通过 webpack.[plugin-name] 访问这些插件。请查看 插件页面 获取插件列表和对应文档, 但请注意这只是其中一部分,社区中还有许多插件。

    如果你想自己写一个插件,请参考如何 编写一个插件

    这里我紧用了几个插件示例。

    html-webpack-plugin 插件:可以为我们动态生成 html 文档,并自动引入「output」打包之后的文档到该 html 文档中。

    clean-webpack-plugin 插件:在我们每次打包工程之前,它将为我们清空目标输出目录,以保证输出目录中的资源都是我们最后需要的。

  3. 输出 output
    可以通过配置 output 选项,告知 webpack 如何向硬盘写入编译文件。注意,即使可以存在多个 entry 起点,但只能指定一个 output 配置。

    此属性的最低要求,是为其配置一个输出文件的文件名 output.filename

output: {
  filename: 'bundle.js',
}

如果是多个入口起点

output: {
  // filename: 'main.js',
  // 输出文件名格式
  filename: '[name].bundle.' + time + '.js',
  // 输出文件位置
  path: path.resolve(__dirname, 'dist')
}

更多配置请参考 output

  1. 代码分离 optimization
    此特性能够把代码分离到不同的 bundle 中,然后可以按需加载或并行加载这些文件。代码分离可以用于获取更小的 bundle,以及控制资源加载优先级,如果使用合理,会极大影响加载时间。

    常用的代码分离方法有三种:

    • 入口起点:使用 entry 配置手动地分离代码。
    • 防止重复:使用 Entry dependencies 或者 SplitChunksPlugin 去重和分离 chunk。
    • 动态导入:通过模块的内联函数调用来分离代码。

    这里用了「防止重复」的方式,并使用了 SplitChunksPlugin 插件,可以将公共的依赖模块提取到已有的入口 chunk 中,或者提取到一个新生成的 chunk。

  2. 模块 module
    模块 选项决定了如何处理项目中的 不同类型的模块。

    在这里我使用了一些加载模块 loader,都在 rules 中配置。这些 loader 可能来自第三方,需要我们单独安装它们才能正常使用。

    [Rule]

    创建模块时,匹配请求的规则数组。这些规则能够修改模块的创建方式。 这些规则能够对模块(module)应用 loader,或者修改解析器(parser)。

你可能感兴趣的:(Webpack 常用配置)