webpack指南

目录

起步

资源管理

加载css

加载images图像

加载fonts字体

加载数据

管理输出

设置HtmlWebpackPlugin

清理 /dist文件夹

manifest

开发环境

使用source map

webpack-dev-middleware

代码分离

防止重复

SplitChunksPlugin

动态导入来分离代码

预获取/预加载模块(prefetch/preload module)

缓存

输出文件的文件名(output  filename)

提取引导模板(extracting  boilerplate)

模板标识符(module  identifier)

创建library

构建性能

loader

引导(bootstrap)

解析

dll

小即是快(smaller = faster)

worker 池(worker pool)

持久化缓存

自定义 plugin/loader

开发环境  增量编译

开发环境  在内存中编译

开发环境  避免在生产环境下才会用到的工具

开发环境  最小化 entry chunk

生产环境  Source  Maps相当消耗性能

安装

模块热替换

启动HMR

HMR加载样式

Tree Shaking

将文件标记为 side-effect-free(无副作用)

解释 tree shaking 和 sideEffects

将函数调用标记为无副作用

结论

生产环境

配置

指定mode

压缩(Minification)

源码映射(Source Mapping)

压缩css

懒加载

ECMAScript 模块

Shimming 预置依赖

TypeScript

导入其他资源

Web Workers

渐进式网络应用程序

公共路径

在运行时设置

资源模块

自定义输出文件名

inline 资源(inlining asset)

自定义 data URI 生成器

source 资源(source asset)

URL 资源

变更内联 loader 的语法

entry 高级用法

每个入口使用多种文件类型


起步

webpack用于编译javascript模块。

webpack-cli用于在命令中运行webpack。

资源管理

webpack将动态打包所有依赖(创建所谓的以来图)。每个模块都可以明确表述自身的依赖,可以避免打包未使用的模块。

webpack最出色的功能之一是,除了引入javascript,还可以通过loader或内置的Asset  Modules引入任何其它类型的文件。

加载css

为了在js模块中import一个css文件,需要使用style-loader(把css插入到dom中)和css-loader(讲css转换成commonJs模块)进行解析。

rules.use中的loader,倒序执行,从后往前的顺序解析执行。第一个被执行的loader将结果(被转换后的资源)传递给下一个loader,依此类推,最后,webpack期望链中的最后的loader返回js。

加载images图像

用webpack5内置的Asset  Modules实现

webpack.config.js:

// ...
rules: [
    {
        test: /\.(png|svg|jpg|jpeg|gif)$/i,
        type: 'asset/resource',
    }
]
// ...

加载fonts字体

用webpack5内置的Asset  Modules实现

// ...
rules: [
    {
        test: /\.(woff|woff2|eot|ttf|otf)$/i,
        type: 'asset/resource',
    }
]
// ...

加载数据

可以加载的有用资源还有数据,如json文件,CSV,TSV和XML。

[{  test: /\.(csv|tsv)$/i,use: ['csv-loader'] },{  test: /\.(xml)$/i,use: ['xml-loader'] }]

管理输出

假如全部手动管理index.html应用程序复杂或出现文件名使用了hash输出多个bundle时,手动管理维护很困难。所以需要使用HtmlWebpackPlugin(维护index.html文件)来解决这个问题。

设置HtmlWebpackPlugin

webpack.config.js

const HtmlWebpackPlugin = require("html-webpack-plugin");
// ...
plugins:[
    new  HtmlWebpackPlugin({ title:"管理输出" })
]
// ...

清理 /dist文件夹

每次打包的时候,webpack会先将dist目录下的文件给删除,然后再将新打包出来的文件放在dist目录下。可以使用output.clean配置项实现这个需求。

manifest

webpack通过manifest,可以追踪所有模块输出bundle之间的映射。

通过WebpackManifestPlugin插件,可以将manifest数据提取为一个json文件以供使用。

开发环境

module.exports = { mode: "development", // ..... }

使用source map

为了方便跟踪error和warning,js提供了source  map功能,可以将编译后的代码映射会原始源代码

webpack-dev-middleware

webpack-dev-middleware是一个封装器,它可以把webpack处理过的文件发送到一个server。

webpack-dev-server内部使用了它,然后它也可以作为一个单独的package来使用,以便根据需求进行更多自定义设置。

代码分离

代码分离是webpack中最引人注目的特性之一。该特性能把代码分离到不同的bundle中,然后可以按需加载或并行加载这个文件。

代码分离可以用于获取更小的bundle,以及控制资源加载优先级,如果使用合理,会极大印象加载时间。

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

        1.入口起点:使用entry配置手动分离代码(在entry属性配置多个入口),缺点:如果入口chunk之间包含一些重复的模块,那些重复模块都会被引入到各个bundle中;

        2.防止重复:使用Entry dependencies或SplitChunksPlugin去重和分离chunk

        3.动态导入:通过模块的内联函数调用来分离代码;

防止重复

入口依赖(Entry  dependencies)配置dependOn  option选项,可以在多个chunk之间共享模块。

注:enrty为多个的情况。

运行结果会生成两个公共模块:shared.bundle.js和runtime.bundle.js;

SplitChunksPlugin

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

module.exports = {
    // ...
    optimization:{
        splitChunks:{
            chunks:"all"
        }
    }
}

动态导入来分离代码

预获取/预加载模块(prefetch/preload module)

eg: <link  rel="prefetch/repload"   href="login-modal-chunk.js" />

缓存

打包完后会生成一个dist文件夹,将dist目录放在部署的server上,浏览器就能够访问此server网站和资源。但是获取资源比较耗时,所以浏览器使用了缓存技术。可以通过缓存技术来降低网络流量,使网站加载速度更快。

输出文件的文件名(output  filename)

使用[contenthash]根据资源内容创建出唯一hash值。当资源内容发生变化时,[contenthash]也会发生变化。

// ....
outputs:{
    filename: '[name].[contenthash].js'
},
// ....

提取引导模板(extracting  boilerplate)

webpack还提供了一个优化功能,可以使optimization.runtimeChunk选项将runtime代码分为一个单独的chunk。

模板标识符(module  identifier)

创建library

// ...
output:{
    // ...
    library: {
        name:"webpackNumbers",
        type:"umd"
    }
}
// ...

创建自己的npm包:Contributing packages to the registry | npm Docs

构建性能

loader

将loader应用于最少数量的必须模块。

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

// ...
rules:[
    {
        test:/\.js$/,
        include:path.resolve(__dorname,"src"),
        loader:"babel-loader"
    }
]

引导(bootstrap)

每个额外的loader/plugin都有其启动时间。尽量少地使用工具。

解析

以下步骤可提高打包速度

        1.减少resolve.modules、resolve.extensions、resolve.mainFiles、resolve.descriptionFiles中条目数量,因为他们会增加文件系统调用的次数。

        2.如果你不使用 symlinks(例如 npm link 或者 yarn link),可以设置 resolve.symlinks: false;

        3.如果你使用自定义 resolve plugin 规则,并且没有指定 context 上下文,可以设置 resolve.cacheWithContext: false

dll

使用 DllPlugin 更改不频繁的代码生成单独的编译结果。这可以提高应用程序的编译速度,尽管它增加了构建过程的复杂度。

小即是快(smaller = faster)

减少编译结果的整体大小,以提高构建性能。尽量保持 chunk 体积小

  • 使用数量更少/体积更小的 library。
  • 在多页面应用程序中使用 SplitChunksPlugin
  • 在多页面应用程序中使用 SplitChunksPlugin ,并开启 async 模式。
  • 移除未引用代码。
  • 只编译你当前正在开发的那些代码。

worker 池(worker pool)

thread-loader 可以将非常消耗资源的 loader 分流给一个 worker pool。

持久化缓存

在 webpack 配置中使用 cache 选项。使用 package.json 中的 "postinstall" 清除缓存目录。

module.exports = { cache: false }

自定义 plugin/loader

 对它们进行概要分析,以免在此处引入性能问题。

开发环境  增量编译

使用 webpack 的 watch mode(监听模式)。

开发环境  在内存中编译

下面几个工具通过在内存中(而不是写入磁盘)编译和 serve 资源来提高性能:

  • webpack-dev-server
  • webpack-hot-middleware
  • webpack-dev-middleware

开发环境  避免在生产环境下才会用到的工具

开发环境  最小化 entry chunk

生产环境  Source  Maps相当消耗性能

安装

"script": {
    "build": "webpack  --config  webpack.config.js"
}

模块热替换

模块热替换(hot  module  replacement 或HMR)是webpack提供的最有用功能之一。它允许在运行时更新所有类型的模块,而无需完全刷新。

启动HMR

更新webpack-dev-server配置,然后使用webpack内置的HMR插件。webpack-dev-server v4.0.0开始,热模块替换默认开启的。

// ...
devServer: {
    hot: true
}
// ...

HMR加载样式

借助于style-loader,使用模块热替换来加载css实际上极其简单。此 loader 在幕后使用了 module.hot.accept,在 CSS 依赖模块更新之后,会将其 patch(修补) 到 <style> 标签中

Tree Shaking

tree shaking 是一个术语,通常用于描述移除 JavaScript 上下文中的未引用代码(dead-code)。它依赖于 ES2015 模块语法的 静态结构 特性,例如 import 和 export

将文件标记为 side-effect-free(无副作用)

通过 package.json 的 "sideEffects" 属性,来实现这种方式。

{
  "name": "your-project",
  "sideEffects": false
}

解释 tree shaking 和 sideEffects

将函数调用标记为无副作用

结论

我们学到为了利用 tree shaking 的优势, 你必须...

  • 使用 ES2015 模块语法(即 import 和 export)。
  • 确保没有编译器将您的 ES2015 模块语法转换为 CommonJS 的(顺带一提,这是现在常用的 @babel/preset-env 的默认行为,详细信息请参阅文档)。
  • 在项目的 package.json 文件中,添加 "sideEffects" 属性。
  • 使用 mode 为 "production" 的配置项以启用更多优化项,包括压缩代码与 tree shaking。

生产环境

配置

开发环境中,我们需要:强大的 source map 和一个有着 live reloading(实时重新加载) 或 hot module replacement(热模块替换) 能力的 localhost server。而生产环境目标则转移至其他方面,关注点在于压缩 bundle、更轻量的 source map、资源优化等,通过这些优化方式改善加载时间。

建议:分别为两个环境编写彼此独立的webpack配置。写一个公共的配置:webpack.common.js,根据环境分别写一个配置文件:webpack.dev.js和webpack.prod.js,最后通过webpack-merge工具来合并处理。

package.json文件:

{
    "name":"lowcode",
    "start":"webpack  serve  --open  --config  webpack.dev.js",
    "build":"webpack  --config  webpack.prod.js"
}

指定mode

process.env.NODE_ENV可获取环境变量。

压缩(Minification)

生产环境下默认使用 TerserPlugin,比较受欢迎的插件:ClosureWebpackPlugin;

源码映射(Source Mapping)

  module.exports = merge(common, {
      mode: 'production',
      devtool: 'source-map',
  });

压缩css

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");

module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      filename: "[name].css",
      chunkFilename: "[id].css",
    }),
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, "css-loader"],
      },
    ],
  },
  optimization: {
    minimizer: [
      // For webpack@5 you can use the `...` syntax to extend existing minimizers (i.e. `terser-webpack-plugin`), uncomment the next line
      // `...`,
      new CssMinimizerPlugin(),
    ],
  },
};

懒加载

懒加载或者按需加载,是一种很好的优化网页或应用的方式。

ECMAScript 模块

ECMAScript 模块(ESM)是在 Web 中使用模块的规范。 所有现代浏览器均支持此功能,同时也是在 Web 中编写模块化代码的推荐方式。

导出export、导入import、将模块标记为ESM;

Shimming 预置依赖

webpack compiler 能够识别遵循 ES2015 模块语法、CommonJS 或 AMD 规范编写的模块。

TypeScript

用ts-loader进行解析;ts-loader可以解析ts文件和tsx文件;

  // ...
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: 'ts-loader',
        exclude: /node_modules/,
      },
    ],
  },
  resolve: {
    extensions: ['.tsx', '.ts', '.js'],
  },
  // ...

如果使用了babel-loader进行代码转换,需要使用@babel/preset-typescript来编译ts文件,使用@babel/plugin-transform-typescript插件来做类型检测。

导入其他资源

想要在 TypeScript 中使用非代码资源(non-code asset),我们需要告诉 TypeScript 推断导入资源的类型。在项目里创建一个 custom.d.ts 文件,这个文件用来表示项目中 TypeScript 的自定义类型声明。

custom.d.ts

declare module '*.svg' {
  const content: any;
  export default content;
}

通过指定任何以 .svg 结尾的导入(import),将 SVG 声明(declare) 为一个新的模块(module),并将模块的 content 定义为 any。我们可以通过将类型定义为字符串,来更加显式地将它声明为一个 url。同样的概念适用于其他资源,包括 CSS, SCSS, JSON 等。

Web Workers

从 webpack 5 开始,你可以使用 Web Workers 代替 worker-loader

渐进式网络应用程序

公共路径

publicPath 配置选项在各种场景中都非常有用。你可以通过它来指定应用程序中所有资源的基础路径。

在运行时设置

webpack暴露了一个名为__webpack_public_path__的全局变量。

__webpack_public_path__ = process.env.ASSET_PATH;

资源模块

资源模块(asset module)是一种模块类型,它允许使用资源文件(字体,图标等)而无需配置额外 loader。

在 webpack 5 之前,通常使用:

资源模块类型(asset module type),通过添加 4 种新的模块类型,来替换所有这些 loader:

  • asset/resource 发送一个单独的文件并导出 URL。之前通过使用 file-loader 实现。
  • asset/inline 导出一个资源的 data URI。之前通过使用 url-loader 实现。
  • asset/source 导出资源的源代码。之前通过使用 raw-loader 实现。
  • asset 在导出一个 data URI 和发送一个单独的文件之间自动选择。之前通过使用 url-loader,并且配置资源体积限制实现。
// ...
rules:[
    {
        test: /\.png/,
        type: 'asset/resource'
    }
]
// ...

自定义输出文件名

默认情况下,asset/resource 模块以 [hash][ext][query] 文件名发送到输出目录。

output:{
    // ...
    assetModuleFilename: 'images/[hash][ext][query]'
}

inline 资源(inlining asset)

rules:{
    // ...
    test: /\.svg/,
    type: 'asset/inline'
}
// 使用
import metroMap from './images/metro.svg';
block.style.background = `url(${metroMap})`;
//url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDo...vc3ZnPgo=)

所有 .svg 文件都将作为 data URI 注入到 bundle 中。

自定义 data URI 生成器

const svgToMiniDataURI = require('mini-svg-data-uri');

// ...
rules:[
    {
        generator: {
         dataUrl: content => {
           content = content.toString();
           return svgToMiniDataURI(content);
         }
       }
    }
]
// ...

现在,所有 .svg 文件都将通过 mini-svg-data-uri 包进行编码。

source 资源(source asset)

rules:{
    test: /\.txt/,
    type: 'asset/source',
}
// 使用
import exampleText from './example.txt';
block.textContent = exampleText; // 'Hello world'

所有 .txt 文件将原样注入到 bundle 中。

URL 资源

变更内联 loader 的语法

entry 高级用法

每个入口使用多种文件类型

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值