likes
comments
collection
share

揭秘webpack5:功能解析与应用

作者站长头像
站长
· 阅读数 27

引言

Webpack5,新一代的打包工具,我们一起来看看它都有哪些新玩法吧!首先,持久化缓存,听起来就像是一个续航能力超强的手机,是不是?实际上,它能帮助我们在构建过程中,将一些结果缓存下来,再次构建时可以直接使用,提高效率。然后是模块联邦,这个听起来就像是联合国一样的存在,实际上,它能帮助我们在不同的构建之间进行模块共享,这样就能减少重复代码,提高性能。再来就是更好的树摇优化,这个不是在摇树,而是可以更好的去除我们代码中的无用代码。

接下来我们要说的是新的资源模块类型,这个就像是我们的电脑中的各种文件类型,可以支持更多的模块类型。然后是更好的代码生成,顾名思义,就是生成代码更好了,更优雅,更高效。然后是实验性的顶级 await,这个听起来就像是一个高级的技能,它在你需要等待某些操作完成后再执行后续操作时就能派上用场。然后是改进的算法和默认值,这个就是在细节上的提升,使得我们的打包效率更高。

最后我们要说的是移除了Node.js Polyfills,这个就是告诉我们,Webpack5更加关注前端,更加侧重于浏览器环境。最后,我们还有更好的长期缓存,这个就像是一个长期记忆,可以帮助我们更好地利用

一、持久化缓存

Webpack5的持久化缓存是一个重要的新特性,它的主要目标是提高构建速度。在Webpack4及其之前的版本中,每次构建都需要从头开始,这在大型项目中可能会导致构建时间过长。而Webpack5的持久化缓存特性则可以将部分模块的构建结果保存下来,从而在下一次构建时直接使用,避免了重复的计算和处理,大大提高了构建速度。

具体来说,持久化缓存的实现主要依赖于两个核心概念:缓存标识符和缓存结果。缓存标识符是一个字符串,它代表了模块的某个特定版本。当模块的源代码或其依赖发生变化时,缓存标识符也会随之改变。而缓存结果则是模块的构建结果,它将在下一次构建时被重用。

开发者可以在webpack配置中启用持久化缓存,只需要将配置对象的cache属性设置为一个对象,其中包含了type属性和buildDependencies属性。type属性的值可以是'memory'或者'filesystem',分别表示使用内存缓存和文件系统缓存。而buildDependencies属性则是一个数组,包含了所有影响缓存结果的文件路径。

持久化缓存的引入,不仅提高了构建速度,还使得开发者更加便捷地进行增量构建和持续集成,大大提升了开发效率和用户体验。

二、模块联邦

在Webpack 5中,新增的模块联邦功能,此功能为开发者提供了一种新的方式来共享和使用代码。模块联邦允许一个JavaScript应用动态的从另一个bundle加载模块,这就像是JavaScript应用之间的微前端。

这项技术可以让你在一个项目中,引用另一个项目的模块。这种方式比之前的DllPlugin或者externals方式都要优雅和方便。在使用模块联邦的时候,引用的模块会作为一个远程入口,你可以像使用本地模块一样使用远程模块。并且在打包的时候,webpack会跳过这些远程模块,使得打包后的代码更小,加载速度更快。

例如,你有两个项目,分别是项目A和项目B,项目B需要使用项目A中的模块。在Webpack 5中,你可以这样配置:

// 项目A的webpack.config.js
module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    publicPath: 'http://localhost:3001/',
  },
  plugins: [
    new ModuleFederationPlugin({
      name: 'projectA',
      filename: 'remoteEntry.js',
      exposes: {
        './Button': './src/Button',
      },
    }),
  ],
};

// 项目B的webpack.config.js
module.exports = {
  entry: './src/index',
  output: {
    filename: 'main.js',
  },
  plugins: [
    new ModuleFederationPlugin({
      name: 'projectB',
      remotes: {
        projectA: 'projectA@http://localhost:3001/remoteEntry.js',
      },
    }),
  ],
};

三、更好的Tree Shaking优化

在 Webpack 5中,Tree Shaking优化得到了进一步的优化和提升。Tree Shaking是一个在静态模块系统中,删除 JavaScript 上下文中未引用代码的过程。这意味着,如果你的代码中存在一些未被使用或引用的导出函数或变量,那么在打包的最终结果中,这些未被使用的代码就不会出现。

在 Webpack 5中,Tree Shaking优化得到了进一步的增强。首先,Webpack 5可以更好地处理嵌套模块。在之前的版本中,如果一个模块是由其他多个模块嵌套而来,那么这个模块中未被使用的部分将不会被摇掉。然而在 Webpack 5中,即使是嵌套模块中的未使用代码,也可以被成功的摇掉。

其次,Webpack 5在处理动态导入(dynamic imports)时,也对Tree Shaking进行了优化。在之前的版本中,如果你使用动态导入,那么整个模块都会被打包进来,而不管这个模块中的哪些部分被使用了。在 Webpack 5中,即使是动态导入的模块,只要其中的部分未被使用,就可以被摇掉。

最后,Webpack 5对于副作用(side effects)的处理也做了优化。在之前的版本中,如果一个模块中的某个功能存在副作用,那么这个功能就不会被摇掉,即使它未被使用。在 Webpack 5中,你可以通过在package.json中设置"sideEffects": false来告诉Webpack,忽略这个模块的副作用,从而让未使用的部分

四、新的资源模块类型

在Webpack 5中,新的资源模块类型取代了原先的raw-loader、url-loader和file-loader。这是一个重要的改进,它意味着开发者无需再安装和配置这些loader。

新的资源模块类型包括以下三种:

● Asset Resource:替代了file-loader,在导入的资源大小超过配置的限制时,会生成一个新的文件,并在JS中返回文件路径。

● Asset Inline:替代了url-loader,在导入的资源大小未超过配置的限制时,会返回一个Data URI。

● Asset:这是一个在资源大小超过限制时自动选择Asset Resource,未超过时选择Asset Inline的智能类型。它取代了url-loader和file-loader的结合使用。

这些新的资源模块类型极大地简化了资源的处理方式,使得开发者可以更加专注于应用逻辑的实现,而不是配置处理资源的loader。例如,要使用Asset Resource模块类型,只需要在webpack.config.js中添加对应的模块规则即可:

module: {
  rules: [
    {
      test: /.(png|jpe?g|gif)$/i,
      type'asset/resource',
    },
  ],
},

这个配置意味着对于所有的png、jpg和gif文件,Webpack都会生成一个新的文件,并在JS中返回文件路径。这样,开发者就可以很方便地在代码中使用这些资源了。

总的来说,新的资源模块类型是Webpack 5的一个重要新功能,它不仅简化了资源处理的方式,也减少了开发者的配置负担。

五、更好的代码生成

Webpack5 在代码生成方面做了很多优化和提升,使得生成的代码更加高效、更加简洁。具体表现在以下几个方面:

一是在代码生成阶段,Webpack5 对于模块引用的处理更加智能。在 Webpack4 和更早的版本中,每个模块的引用都会生成一段代码,即使这个模块在运行时并不需要。而在 Webpack5 中,只有当模块在运行时真正需要时,才会生成相应的引用代码。这样可以避免无用的代码生成,提升了代码的效率。

二是Webpack5 对于代码的压缩也做了优化。在 Webpack4 中,代码的压缩主要通过 UglifyJS 插件进行。而在 Webpack5 中,引入了新的 Terser 插件进行代码压缩。Terser 插件在压缩效果上不仅优于 UglifyJS,而且在处理 ES6 代码时,能够生成更加简洁的代码。

三是Webpack5 在代码生成的过程中,对于模块的处理也进行了优化。在 Webpack4 中,模块的处理是全局性的,这意味着同一份代码在不同的模块中会被重复生成。而在 Webpack5 中,引入了模块级别的代码生成,即只有当模块在运行时真正需要时,才会生成相应的代码。这样可以避免无用的代码生成,提升了代码的效率。

综上所述,Webpack5 在代码生成方面做了很多优化和提升,使得生成的代码更加高效、更加简洁。这对于开发者来说,不仅可以提升开发效率,而且可以降低项目的运行成

六、实验性的顶级 await

在 webpack 5 中,实验性的顶级 await 是一个新引入的特性。这项特性允许你在模块顶级作用域中直接使用 await 关键字,而无需将其包裹在一个异步函数中。这对于在模块初始化时需要等待异步操作(例如读取配置文件或检索资源)的场景非常有用。

顶级 await 的使用示例如下:

JavaScript1const config = await fetch('/config.json');
2console.log(config);

在上述代码中,fetch 是一个返回 Promise 的异步函数,而 await 则用于等待这个 Promise 完成,并获取其返回的结果。由于使用了顶级 await,因此整个模块的求值会等待 fetch 完成。这意味着如果其他模块依赖于此模块,那么它们也会等待此模块完成。

需要注意的是,由于顶级 await 会阻塞模块的求值,因此它可能会影响应用程序的启动性能。因此,虽然这是一个强大的特性,但是它应该谨慎使用,尽量避免在大量模块中使用顶级 await。

此外,顶级 await 目前还是 ECMAScript 的提案阶段,并未被所有的 JavaScript 环境支持。不过,由于 webpack 5 已经支持这个特性,因此你可以在使用 webpack 的项目中放心使用。

七、改进的算法和默认值

Webpack 5引入了一些改进的算法和默认值,这些改进和更改旨在提升构建性能和输出结果的质量。

在算法方面,Webpack 5采用了新的长期缓存算法。在Webpack 4中,文件的hash值是基于整个构建的,这意味着即使只有一个文件发生了变化,所有文件的hash值也会改变,这对于长期缓存并不友好。而在Webpack 5中,文件的hash值仅基于自身的内容和查询参数,这样即使在构建中的其他部分发生变化,只要文件本身没有改变,其hash值就会保持不变,这大大提高了缓存的效率。

在默认值方面,Webpack 5改变了一些默认的插件和加载器的配置,以优化构建结果。例如,新的默认JavaScript minimizer是terser-webpack-plugin,它比之前默认的uglifyjs-webpack-plugin有更好的压缩效果和构建性能。另一个例子是,新版Webpack默认启用了tree shaking和module concatenation,这可以减少输出的代码量和提高代码运行效率。

这些改进的算法和默认值,使得Webpack 5在构建性能和输出质量上都有了显著的提升。同时,这些改变也显示出Webpack对于不断改进和优化的决心和能力,使得它仍然是前端构建工具的首选。

八、移除了Node.js Polyfills

自webpack 5开始,webpack不再自动包括Node.js核心模块的polyfills,这是一项重要的改变,将有助于提高打包的效率和性能。在之前的版本中,webpack会自动包括一些Node.js的核心模块,如path和fs等,但这些模块在浏览器环境下通常是无法工作的。这就导致了打包后的代码体积增大,且包含了很多无法在浏览器环境下使用的代码。

这项改变主要是为了改善打包效果,让最终的bundle更小、更快。对于那些需要在浏览器环境下运行的项目,移除了这些polyfills将会使得最终的bundle大小显著减小。而对于那些需要使用Node.js核心模块的项目,开发者需要手动添加这些polyfills。

这也意味着,如果你的项目中依赖了一些Node.js的核心模块,那么在迁移到webpack 5后,你可能需要对项目做一些调整。例如,你可能需要添加一些额外的配置,以确保这些核心模块可以被正确地解析和打包。

总的来说,这项改变将使得webpack更加灵活,可以更好地适应不同的项目需求。同时,它也体现了webpack团队对于提高打包效率和性能的持续追求。

九、更好的长期缓存

Webpack 5在长期缓存方面做了重要的改进。在版本4中,即使在代码没有任何改变的情况下,编译后的文件的哈希值也会发生变化,这意味着浏览器无法有效地缓存这些文件。然而,在Webpack 5中,这个问题得到了解决。

为了实现更好的长期缓存,Webpack 5引入了一种新的缓存机制:持续性缓存。与传统的内存缓存不同,持续性缓存会将缓存数据储存在硬盘中,这样即使在电脑重启后,缓存数据依然能够被保留。这个特性将显著提高重复构建的速度。

在Webpack 5中,只有在实际的源文件发生改变时,生成的哈希值才会发生变化。这意味着,如果文件内容未发生改变,那么编译后的文件名将会保持不变,从而使得浏览器能够更好的缓存文件。

除此之外,Webpack 5还引入了一种新的算法来生成编译后的文件名。这种算法能够确保在大部分情况下,文件的内容发生微小变化时,生成的文件名还能保持不变。这进一步优化了浏览器的缓存机制,提高了应用的加载速度。

总的来说,Webpack 5在长期缓存方面的改进,将有助于提高应用的加载速度,提升用户体验。在未来的版本中,我们有理由期待Webpack会在这一方面做出更多的优化。

总结

好了,让我们将webpack5的这次冒险之旅画上一个完美的句号!我得说,webpack5的新功能就像一个盛装的魔术师,一次又一次的惊喜让人目不暇接。持久化缓存让我们的构建速度快如闪电,模块联邦让不同的应用可以互相分享代码,像一个大家庭一样,互帮互助。更好的树摇优化,让我们的应用瘦身成功,不再有多余的肉肉。新的资源模块类型,更好的代码生成,就像给代码穿上了华丽的礼服,让它更加亮丽夺目。实验性的顶级await,改进的算法和默认值,简直是开发者的福音,让编程变得更加得心应手。移除了Node.js Polyfills,更好的长期缓存,让我们的应用更加稳定,运行更加顺畅。总的来说,webpack5的这些新功能真是太棒了,让人忍不住想要马上动手试试!

转载自:https://juejin.cn/post/7368001339443052554
评论
请登录