Allen's blog Allen's blog
首页
面经
算法 (opens new window)
分类

Allen

前端CV工程师
首页
面经
算法 (opens new window)
分类
  • Javascript

  • TypeScript

  • CSS

  • Vue

  • React

  • 框架和构建工具

    • rollup使用配置文件rollup.config.ts打包
    • webpack学习笔记
      • 为什么要使用 webpack
      • webpack 配置文件
      • 使用 Webpack Loader
        • 加载 CSS
        • 加载图片
      • 使用插件
        • 自动生成 index.html
        • 转译 ES6 为 ES5 插件
        • 压缩 JS 代码
      • Dev Server 开发服务器
      • 文件名缓存
      • 路径别名
      • 管理输出
        • HtmlWebpackPlugin
        • 清理 dist 文件夹(出口文件夹)
        • manifest
      • 开发环境
        • source map
        • 源代码改变后自动编译(webpack-dev-server)
        • watch mode
        • webpack-dev-server
        • webpack-dev-middleware
        • 代码分离
        • 防止重复(prevent duplication)
        • 入口依赖
        • SplitChunksPlugin
        • 动态导入
        • 预获取/预加载模块
        • 缓存
        • 修改输出文件名
        • 提取引导模板(boilerplate)
        • 模板标识符
        • 创建库(library)
        • 暴露库(expose library)
        • 外部化 lodash
        • 外部化的限制
        • 生产环境
        • webpack 环境变量
        • 构建性能
        • loader
        • 引导(bootstrap)
    • vite学习笔记
    • PostCSS学习笔记
    • nuxt3项目搭建与配置
    • ts、vite、vitepress配置别名alias
  • 工具库

  • 常见业务场景

  • Bug

  • 项目实战

  • 前端
  • 框架和构建工具
Allen
2023-02-13
目录

webpack学习笔记

参考文章:峰华前端工程师的 Webpack 入门教程 (opens new window)

听了 B 站 UP(峰华前端工程师 (opens new window))讲解webpack,决定重新整理一下笔记,webpack教程很多,对于新手来说,阅读webpack的文档时常会感到头晕,因为webpack功能强大,插件丰富,在学习的时候,不容易抓到主线。

导致之前做笔记的时候,大多是进行文档摘抄,没有一个全局的理解,这次重新编辑一下,梳理一下逻辑

webpack是一个打包工具,它可以将一个入口js文件,梳理 js 文件的依赖情况,将依赖的所有 js 代码打包到一个或多个文件中,这是它的基本功能。

通过webpack的丰富的loader,我们可以增加webpack的打包能力,可以解析除了.js后缀以外的其他文件,如.vue、.css、.png、.svg文件等。

webpack不仅是有打包文件的能力,还有解决文件名缓存,设置路径别名,代码分析等功能,还可以借助插件,可以增加 ES6 转义 ES5、热更新、代码压缩、DevServer 的能力

下面将记录一下webpack的作用、loader 使用、插件使用以及配置文件名缓存、路径别名、ES6 转义 ES5,热更新、代码压缩、DevServer 等功能

# 为什么要使用 webpack

我们在传统的网页开发项目中,需要通过在 html 中引入大量的 JavaScript、CSS 等文件,不仅会导致命名冲突,还会使页面体积变大,因为如果是第三方库,需要加载所有代码。

<script src="./jquery.js"></script>
<script src="./index.js"></script>
<script src="./home.js"></script>
1
2
3
// index.js
var a = 1

// home.js
var a = 2
1
2
3
4
5

而在 node.js 出现之后,JavaScript 项目支持通过 require 进行模块化开发了,并且支持 npm 方便的管理依赖:

npm install someLib

require("someLib");
1
2
3

借着 Node.js 和浏览器 JS 语法的一致性,前端项目开始在 node.js 下开发,完成之后,把代码构建成浏览器支持的形式。对于 react 或 vue 这种组件化开发方式,因为有很多分散的文件,那么就特别需要这样的构建操作。 Webpack 就是进行这一步构建操作的,把 Node.js 模块化的代码转换为浏览器可执行的代码。它提供了 import 和 export ES 6 模块化的语法支持,然后通过分析代码中的 import 导入的依赖,把需要的代码加载进来。 在 webpack 中,任何文件都可以通过 import 导入,只要有对应的 loader 就可以:

import 'style.css'
import 'image/avatar.png'
1
2

在打包过程中还可以通过插件干预打包过程,例如剔除不必要的代码,形成体积更小的项目。 好,我们具体的来看一个使用 webpack 打包项目的例子。

# webpack 配置文件

Webpack 最核心的一个部分是它的配置文件,在里边我们可以修改入口的 JS 文件,也就是说从哪个文件里边开始寻找 import 依赖,还可以配置出口,也就是最后生成的 JS 文件的一些信息,还能够通过 loader 加载不同类型的文件,再可以通过 plugins 在打包的过程中,对代码进行一些优化或者其他的操作。 我们来测试一下看看,把打包后的文件名修改一下,我们在这里先新建一个 webpack.config.js 文件,这里边使用的是 Node.js 的模块化语法,使用 module.exports,导出一个空的对象,在里边我们配置 webpack 的配置项:

  1. 我们添加一个 mode 属性,因为我们之前打包的时候,命令行提示了这个 mode 选项没有设置, webpack 默认取的是 production,但是我们也可以设置为 development 开发环境,这样的话在开发环境下, webpack 打包的代码会不太一样,方便我们开发者进行调试,这里我们把 mode 先设置成 development。

  2. 看一下 entry,这里我们还是取的默认值,可以把它拿出来,看一下是怎么设置的,这里可以直接把咱们的入口文件路径给它写上,./src/index js。

  3. 配置打包后的文件名,我们使用 output 配置项,传递一个对象属性,配置 filename,这个就是打包后的文件名,例如我们改成 dist.js,然后存放目录也可以改一下,现在是 dist,如果要改成别的话,可以给它配置一个 path 属性,这里我们可以利用 Node.js 提供的 path 库,来获取 webpack.config.js 所在的目录,基于它我们再去找到一个新的目录,来存放我们打包后的文件,例如说我们还是把它放到 dist 里边。我们可以调用 path.resolve(),resolve 接收多个参数可以指定多级目录,例如第一级我们设置为 __dirname,然后第二级设置为 dist,这样它就会放到 dist 目录下边了,你也可以把它改成别的名字。

const path = require('path')

module.exports = {
    entry: './src/index.js',
    output: {
        filename: 'dist.js',
        path: path.resolve(__dirname, 'dist')
    }
}
1
2
3
4
5
6
7
8
9

# 使用 Webpack Loader

# 加载 CSS

要加载 CSS 文件,我们需要安装两个 loader,一个叫 style loader,另一个是 CSS loader。

yarn add style-loader css-loader --dev
1

安装完成之后,我们需要在 webpack 的配置文件里边去配置它,对于 loader,在 webpack 里边,我们需要先去匹配,以什么样的扩展名结尾的文件,去应用什么样的 loader。 在这里我们:

  1. 添加一个 module 配置项。
  2. 在里边配置 rules 配置项,它的值是一个数组,数组里边的每一个元素,都对应一个 loader 的配置,每个 loader 的配置都包含匹配扩展名,以及使用哪些 loader 和它相关的选项,例如说我们这里配置 CSS loader,先给 rules 传递一个对象。
  3. 在对象中配置 test 属性,它的值是一个正则表达式,用于匹配文件名,这里我们匹配所有以 .css 结尾的文件,那么这里我们先传递一个正在表达式,然后使用 \.来匹配文件名里边的点号,因为点号在正则表达式中有特殊的含义,所以需要反/进行转义,然后写上 CSS 这个扩展名,再接着使用一个 $符号,来匹配文件名的结尾,后边我们可以加上一个 i来忽略大小写。
  4. 给它传递一个 use 属性,就是说使用哪些 loader,这里我们使用刚才安装好的 style loader 和 css loader。
// webpack.config.js

  module: {
    rules: [
      {
        test: /\.css$/i, // 匹配文件结尾,正则 - 忽略大小写
        use: ['style-loader', 'css-loader'], // 使用哪些 Loader
      },
    ],
  },
1
2
3
4
5
6
7
8
9
10

# 加载图片

对于图片等静态资源的文件,webpack 原生的支持,所以就不再需要额外的安装 loader 了,我们这里可以:

  1. 直接在 rules 里边,再添加一个配置对象。
  2. 设置 test 属性,这里匹配所有的图片文件,那么我们使用 \.,然后使用一个小括号,里边我们要匹配多种图片的扩展名,例如 png,然后使用 |表示或, svg 或 jpg 或 jpeg 或 gif,然后加上 $,匹配扩展名这个结尾,再加上一个 i 表示忽略大小写。
  3. 这里因为它是使用内置的 loader,所以使用 type 属性,设置 asset/resource 这样的值就可以了。
rules: [
// ...
  {
    test: /\.(png|svg|jpg|jpeg|gif)$/i,
    type: 'asset/resource', // 资源类型
  }
],
1
2
3
4
5
6
7

接下来我们测试一下,先添加一张测试图片,在 src 下新建一个 assets 目录,再在它里边新建一个 images 目录,把图片 copy 过来,然后在 index.js 中创建一个 image 元素,把图片展示出来,这里我们先使用 import 把图片导入进来,给他一个名字,比如叫做 HeroImage,然后 from ./assets/images/hero.jpeg,这样导入之后,HeroImage 表示的就是打包后的图片的真实的路径,可以直接用于 img 元素的 src 属性上面。 接下来我们创建 image 元素,然后设置它的 src 属性值,为我们导入进来的 HeroImage,最后把它添加到 body 里边,这里我要把它放到 body 的开头。

import HeroImage from './assets/images/hero.jpeg' // 打包时替换成真实的路径

const image = document.createElement('img')
image.src = HeroImage
document.body.prepend(image)
1
2
3
4
5

我们打包一下 npx webpack。回到浏览器看一下,这个图片就正常的加载出来了,我们还可以看到在打包之后,这个图片的名字,也变成了随机的字符串。

# 使用插件

# 自动生成 index.html

根目录下的 index.html 是手写的,非常容易出错,需要同步 src 下边的 JS 文件路径,而 webpack 有一个插件,可以自动生成 html 文件,这样就不需要我们再手动去编写代码了,这个插件叫做 HtmlWebpackPlugin。 我们先安装它,并添加到开发者依赖中:

yarn add html-webpack-plugin --dev
1

打开 webpack.config.js,里边我们使用这个插件: 首先先导入进来,之后在配置对象里边,添加一个 plugins 配置项,它的值是一个数组,在里边我们可以加载多种插件,加上 HtmlWebpackPlugin,它导出的是一个构造函数,我们使用 new 调用它,这样就加载好了这个插件:

const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
    entry: {},
    plugins: [new HtmlWebpackPlugin()]
}
1
2
3
4
5

运行一下 npx webpack,dsit 目录下会多一个 index.html,这个就是它自动帮我们生成的 html 代码

不过看一下这个 html 的标题是默认生成的,HtmlWebpackPlugin 插件支持我们传递参数,来自定义 html 代码的生成。例如,这里可以传递一个 title 属性,设置一下网页的标题,例如叫做博客列表:

new HtmlWebpackPlugin({title: "博客列表"}),
1

# 转译 ES6 为 ES5 插件

我们在开发前端项目的时候,有的时候会使用新的 ECMAScript 特性,但是要兼容低版本的浏览器,那么我们可以利用 Babel 这个工具,来转译咱们的 JS 代码。webpack 也支持相应的 loader,我们看一下来怎么实现。 首先安装 babel-loader,@babel/core,@babel/preset-env 这 3 个依赖:

yarn add --dev babel-loader @babel/core @babel/preset-env
1

安装完成之后:

  1. 在 webpack 配置项里边,我们再新添加一个 loader 配置,这里我们要匹配 JS 结尾的文件,那么使用 test,匹配 ./js 这个扩展名。
  2. 使用 exclude,把 nodule_modules 这个目录给去掉,这样它就不会转译它下边的代码。
  3. 使用 use 来配置使用哪些 loader,这里我们使用对象形式,因为我们需要给 loader,传递一些自定义的配置。
  4. 使用 loader 配置项,指定要使用哪个 loader,我们这里使用 babel loader。
  5. 使用 options 来给这个 loader 传递一些配置,配置 presets,使用 @babel/preset-env,这样就能够自动转译代码了。
  6. 为了方便我们看打包后的代码,我们可以在 webpack 的配置项里,添加一个 devtool 配置项,把它设置为 inline-source map,这样方便我们查看打包后的源代码。
devtool: 'inline-source-map', // 方便查看源码
  module: {
  rules: [
    {
      test: /\.js$/,
      exclude: /node_modules/,
      use: {
        loader: 'babel-loader',
        options: {
          presets: ['@babel/preset-env'],

        }
      }
    }
  ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 压缩 JS 代码

webpack 的另一个常见的场景,就是压缩打包后的 JS 代码,这样的话可以减少打包后的文件体积,他需要一个叫做 terser-webpack-plugin 的插件,我们这里先安装一下:

yarn add --dev terser-webpack-plugin
1

好安装完成之后,我们在 webpack.config.js 里边配置它。

  1. 导入进来,把它保存到一个叫做 terser-webpack-plugin 的常量里边。
  2. 在导出的配置对象里边,添加一个 optimization 配置项,配置 minimize 是否要压缩,把它的值设置为 true。
  3. 配置 minimizer,用什么工具来压缩,我们这里使用安装的 terser-webpack-plugin,这里直接调用 new TerserPlugin() 这个构造函数就可以了。
const TerserPlugin = require('terser-webpack-plugin')

module.exports = {
    optimization: {
        minimize: true,
        minimizer: [new TerserPlugin()]
    }
}
1
2
3
4
5
6
7
8

# Dev Server 开发服务器

现在我们在开发的时候,需要每次在改动 JS 之后都要重新打包,webpack 提供了一个 dev server 开发服务器,它可以在启动之后,如果我们修改的 JS 代码,它就会自动重新打包并刷新页面,我们来看一看怎么来使用这个工具。首先先安装它 :

yarn add --dev webpack-dev-server
1

接下来我们需要指定 dev server 要从哪里去加载代码,我们打开 webpack.config.js,在配置项里边再添加一个 devServer 配置项,给他的值设置为一个对象,然后设置 static,给他指定咱们的 dist 目录:

  devServer: {
    static: './dist', // 从哪里找打包好的文件
  },
1
2
3

接下来,为了方便我们运行开发服务器,我们在 package.json 里边再新添加一个 script,例如,我们可以使用 yarn start 来启动开发服务器,那么这里我们添加一个 scripts 配置项,然后在里边配置 start 命令,值为 webpack serve --open,这样就能够启动 webpack dev server,并自动打开浏览器:

   "scripts": {
     "start": "webpack serve --open", // 自动打开浏览器
   },
1
2
3

# 文件名缓存

现在我们打包后的文件,这个 dist.js 每次都是一样的,但是浏览器会根据这个文件名,进行缓存,一般我们为了避免浏览器进行缓存,我们会给文件名加上一串随机的字符,每次更新之后都改为新的字符,那么 webpack 也支持自动在打包后,生成新的一串字符,我们看一下怎么来实现。 打开 webpack.config.js,这里我们需要

  1. 配置 output,这里 filename 我们配置了 dist.js,但是我们也可以把它改成一个带有 ·,也就是不重复的字符串的文件名。
  2. 把它的值改成 [name][contenthash].js,这里 name 也可以写死,不过写 [name] 的话,webpack 会自动把它替换成 main,就是默认的文件名,contenthash 会每次根据文件的内容进行 hash 计算,得出一串不重复的字符:
output: {
    filename: 'dist.js',
    filename: '[name].[contenthash].js',
    path: path.resolve(__dirname, 'dist'),
},
1
2
3
4
5

# 路径别名

接下来我们看一下,如何给导入的路径设置别名,有的时候,JS 文件所在的目录可能会嵌套的比较深,要引入其他的目录下边的 JS 文件,需要使用很多 ../ 来访问这个相对路径。但是 webpack 可以让我们指定一个路径别名,来把这一串相对路径给替换掉,这样就少写一些字符串。

配置路径别名,打开 webpack.config.js,再添加一个 resolve 配置项,它的值也是一个对象,然后添加 alias 配置项,它里面的属性名就是路径别名,值就是真实的路径:

  resolve: {
    alias: {
      utils: path.resolve(__dirname, 'src/utils/'),
    },
  },
1
2
3
4
5

# 管理输出

# HtmlWebpackPlugin

HtmlWebpackPlugin插件可以自动输出 HTML,并嵌入多个出口 js

# 清理 dist 文件夹(出口文件夹)

webpack 每次打包不会在出口文件夹检测里面的文件是否都用到了,仅仅是将生成的文件放到了输出目录(dist)里面。可以采用output.clean配置项来实现这个构建后没有旧文件。

# manifest

webpack 和 webpack 插件知道哪些文件应该生成,它是通过 manifest 来实现的。可以通过WebpackManifestPlugin插件可以提取一个 json 文件。

# 开发环境

将mode设置为development

# source map

多个依赖最终会打包为一个输出文件,使用 source map 功能可以追踪到错误和警告对应于源代码中的位置

module.exports = {
    devtool: 'inline-source-map'
}
1
2
3

# 源代码改变后自动编译(webpack-dev-server)

webpack 可以做到在源代码发生改变时,提供了几种可选的方式帮助我们自动编译代码,可以根据项目需要选择,浏览器应用一般需要 webpack-dev-server。以下是几种可选方式:

  1. watch mode
  2. webpack-dev-server
  3. webpack-dev-middleware

# watch mode

在 package.json 的 scripts 中配置--watch参数:

{
    "scripts": {
        "watch": "webpack --watch"
    }
}
1
2
3
4
5

这种方式会自动重新编译修改后的模块,唯一的缺点是浏览器需要刷新。

# webpack-dev-server

webpack-dev-server 提供了一个基本的 web server,具有实时重新加载的功能。配置方法是在 webpack.config.json 中添加 devServer 字段:

module.exports = {
    devServer: {
        static: './dist'
    },
    optimizatino: {
        runtimeChunk: 'single'
    }
}
1
2
3
4
5
6
7
8

因为在这个示例中单个 HTML 页面有多个入口,所以添加了 optimization.runtimeChunk: 'single' 配置。没有这个配置的话,我们可能会遇到 这个问题 (opens new window)。 查看 代码分割 (opens new window) 章节获取更多细节。

webpack-dev-server 会从 output.path 中定义的目录中的 bundle 文件提供服务,即文件将可以通过 http://[devServer.host]:[devServer.port]/[output.publicPath]/[output.filename] 进行访问。

添加 scripts 到 package.json

{
    "scripts": {
        "start": "webpack serve --open"
    }
}
1
2
3
4
5

# webpack-dev-middleware

webpack-dev-server 在内部使用了 webpack-dev-middleware,然而 webpack-dev-middleware 也可以单独来使用。比如可以配合 express server 来使用,参考连接 (opens new window)

# 代码分离

一种不够灵活的方式:入口起点包含多个文件时,如果这些文件内部包含相同的依赖,最后的输出将会包含重复的依赖。

# 防止重复(prevent duplication)

# 入口依赖

在入口配置 dependOn 选项,可以在多个 chunk 之间共享模块

const path = require('path')

module.exports = {
    mode: 'development',
    entry: {
        // index: './src/index.js',
        // another: './src/another-module.js',
        index: {
            import: './src/index.js',
            dependOn: 'shared'
        },
        another: {
            import: './src/another-module.js',
            dependOn: 'shared'
        },
        shared: 'lodash'
    },
    output: {
        filename: '[name].bundle.js',
        path: path.resolve(__dirname, 'dist')
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

如果我们要在一个 HTML 页面上使用多个入口时,还需设置 optimization.runtimeChunk: 'single',否则还会遇到这里 (opens new window)所述的麻烦。

module.exports = {
    optimization: {
        runtimeChunk: 'single'
    }
}
1
2
3
4
5
# SplitChunksPlugin

SplitChunksPlugin 插件可以将公共的依赖模块提取到已有的入口 chunk 中,或者提取到一个新生成的 chunk。

module.exports = {
    optimization: {
        splitChunks: {
            chunks: 'all'
        }
    }
}
1
2
3
4
5
6
7

使用 optimization.splitChunks 配置选项之后,现在应该可以看出,index.bundle.js 和 another.bundle.js 中已经移除了重复的依赖模块。需要注意的是,插件将 lodash 分离到单独的 chunk,并且将其从 main bundle 中移除,减轻了大小。

# 动态导入

进行动态代码拆分有两种方式,第一种是采用 EMCAScript 提案的 import()语法,第二种是使用 webpack 遗留功能 require.ensure

import()内部会用到 promise,在旧版本的浏览器中使用需要使用一个 polyfill 库(例如 es6-promise 或 promise-polifill)来 shim Promise

# 预获取/预加载模块

在动态导入的时候,对 import()使用内置指令,可以使得最后生成的 link 标签上有"prefetch"/"preload"

import(/* webpackPrefetch: true */ './path/to/LoginModal.js')
1

会生成,并在浏览器闲置时间预取 login-modal-chunk.js

感觉这一块用来做性能优化的

# 缓存

浏览器缓存机制是为了节省网络流量,提高加载速度。然而在开发时,这不利于调试,因为文件名没有改变时,浏览器会利用缓存,不会更新

# 修改输出文件名

output.filename 可以采用可替换模板字符串的方式来使得每次更改完文件,输出的文件名都不同。

模板规则可以查看:https://webpack.docschina.org/configuration/output/#template-strings (opens new window)

# 提取引导模板(boilerplate)

可以将第三方库(例如 lodash 或 react)提取到单独的 vendor chunk 文件中,他们很少会频繁修改,可以利用浏览器长缓存机制,命中缓存来消除请求。

可以使用 SplitChunksPlugin 插件的 cacheGroups 选项来实现,我们在 optimization.splitChunks 添加如下 cacheGroups 参数并构建:

module.exports = {
    optimization: {
        runtimeChunk: 'single',
        splitChunks: {
            cacheGroups: {
                vendor: {
                    test: /[\\/]node_modules[\\/]/,
                    name: 'vendors',
                    chunks: 'all'
                }
            }
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

这里的single表示输出为一个 runtime chunk 文件

# 模板标识符

每个模块的 id 会默认的基于解析顺序(resolve order)进行增量,即当解析顺序发生改变,id 也会发生改变

我们只期望内容发生改变的模块的输出文件名发生变化,而内容没有修改的模块,它们的输出文件名不要发生改变,尤其是提取引导模块的 vendor chunk 的输出文件名不需要改变。我们将 optimization.moduleIds 设置为 'deterministic':

module.exports = {
    entry: './src/index.js',
    plugins: [
        new HtmlWebpackPlugin({
            title: 'Caching'
        })
    ],
    output: {
        filename: '[name].[contenthash].js',
        path: path.resolve(__dirname, 'dist'),
        clean: true
    },
    optimization: {
        moduleIds: 'deterministic',
        runtimeChunk: 'single',
        splitChunks: {
            cacheGroups: {
                vendor: {
                    test: /[\\/]node_modules[\\/]/,
                    name: 'vendors',
                    chunks: 'all'
                }
            }
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# 创建库(library)

编写一些工具库的时候,可以选择 webpack 来进行打包。

需要安装 webpack、webpack-cli、lodash

需要将他们都安装到 devDependency 中,而不是 dependency,因为我们不需要将他们打包到我们的库中,否则我们的库体积很容易变得很大。

# 暴露库(expose library)

通过 output.library 配置项暴露从入口导出的内容

const path = require('path')

module.exports = {
    entry: './src/index.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'webpack-numbers.js',
        library: 'webpackNumbers'
    }
}
1
2
3
4
5
6
7
8
9
10

将入口七起点公开为 webpackNumbers,这样用户就可以通过 script 标签使用它:

<script src="https://example.org/webpack-numbers.js"></script>
<script>
  window.webpackNumbers.wordToNum('Five');
</script>
1
2
3
4

可以设置 type 来打包一个库

const path = require('path')

module.exports = {
    entry: './src/index.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'webpack-numbers.js',
        library: 'webpackNumbers',
        library: {
            name: 'webpackNumbers',
            type: 'umd'
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

类型默认包括 'var'、 'module'、 'assign'、 'assign-properties'、 'this'、 'window'、 'self'、 'global'、 'commonjs'、 'commonjs2'、 'commonjs-module'、 'commonjs-static'、 'amd'、 'amd-require'、 'umd'、 'umd2'、 'jsonp' 以及 'system',除此之外也可以通过插件添加。

# 外部化 lodash

lodash 会被打包到代码中,更倾向于将 lodash 放到 peerDependency 中,可以通过 externals 配置来完成

const path = require('path')

module.exports = {
    entry: './src/index.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'webpack-numbers.js',
        library: {
            name: 'webpackNumbers',
            type: 'umd'
        }
    },
    externals: {
        lodash: {
            commonjs: 'lodash',
            commonjs2: 'lodash',
            amd: 'lodash',
            root: '_'
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

这意味着你的 library 需要一个名为 lodash 的依赖,这个依赖在 consumer 环境中必须存在且可用。

# 外部化的限制

对于想要实现从一个依赖中调用多个文件的那些 library,

import A from 'library/one'
import B from 'library/two'

// ...
1
2
3
4

无法通过在 externals 中指定整个 library 的方式,将它们从 bundle 中排除。而是需要逐个或者使用一个正则表达式,来排除它们。

module.exports = {
    //...
    externals: [
        'library/one',
        'library/two',
        // 匹配以 "library/" 开始的所有依赖
        /^library\/.+$/
    ]
}
1
2
3
4
5
6
7
8
9

# 生产环境

在 package.json 中添加 main 字段来输出结果

# webpack 环境变量

webpack 命令行参数--env 参数可以传入任意数量的环境变量,在 webpack.config.js 中可以访问到这些环境变量。例如--env production 或--env goal=local

webpack 配置之前默认导出的是一个对象,限制要修改为一个函数以接受 env 环境变量

const path = require('path')

module.exports = (env) => {
    // Use env.<YOUR VARIABLE> here:
    console.log('Goal: ', env.goal) // 'local'
    console.log('Production: ', env.production) // true

    return {
        entry: './src/index.js',
        output: {
            filename: 'bundle.js',
            path: path.resolve(__dirname, 'dist')
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 构建性能

最新版本的 webpack 和 nodejs

# loader

减少 loader 数量

通过 include 字段,仅将 loader 应用在实际需要转换的模块

const path = require('path')

module.exports = {
    //...
    module: {
        rules: [
            {
                test: /\.js$/,
                include: path.resolve(__dirname, 'src'),
                loader: 'babel-loader'
            }
        ]
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 引导(bootstrap)

。。。略

上次更新: 2023/12/16, 09:22:46
rollup使用配置文件rollup.config.ts打包
vite学习笔记

← rollup使用配置文件rollup.config.ts打包 vite学习笔记→

最近更新
01
rollup使用配置文件rollup.config.ts打包
12-08
02
package.json导出类型
12-08
03
关键问题方案
11-17
更多文章>
Theme by Vdoing | Copyright © 2023-2023 Allen | Github
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式