• home > tools > Bundler > webpack >

    webpack5新功能展望

    Author:zhoulujun Date:

    现在最新版本的 webpack4 更新到了 v4 44 1,webpack5 已经到 v5 0 0-beta 25,虽然还没有正式版放出,但是我们也得上车,体验了。v5使用持久化缓存提高构建性能,减小打包后的文件体积,按需加载支持文件名模式

    webpack5 beta0,由sokra released on 11 Oct 2019,2063 commits to master since this release

    当天,webpack更新到 v4.41.1

    现在最新版本的 webpack4 更新到了 v4.44.1,webpack5 已经到 v5.0.0-beta.25

    其中,v5.0.0-beta.23v5.0.0-beta.18v5.0.0-beta.17,Features 都是一个大列表

    虽然还没有正式版放出,但是我们也得上车,体验了

    webpack5新特性总结

    1. 使用持久化缓存提高构建性能,使用cache: {type: "filesystem"}配置实现持久化缓存,提高构建速度;

    2. 使用更好的算法和默认值改进长期缓存(long-term caching),解决生产环境下moduleIds & chunkIds变化的问题;

    3. 清理内部结构而不引入任何破坏性的变化;

    4. 引入一些breaking changes,以便尽可能长的使用v5版本。

    5. 减小打包后的文件体积,按需加载支持文件名模式

    6. 优化minSize&maxSize的配置方式

    7. Node.js polyfills 自动加载功能被移除,Webpack 5 开始将不再自动添加 Polyfill 脚本了,可以有效减少最终编译代码的大小。

    下面细讲

    Persistent Caching

    在 Webpack 编译过程中,如果某个文件发生变化,那么 Webpack 会从 entry 开始,从新递归查找所依赖的模块,然后重新编译。

    Webpack 编译过程

    Webpack 5 中采用持久化缓存来优化整个编译流程:当检测到文件发生变化时,只会对发生变更的文件进行编译,从而提高编译效率。

    默认情况下,持久化缓存是不开启的,可以通过下面的配置启用持久化缓存:

    cache: {
    	// 1. Set cache type to filesystem
      type: "filesystem",
    
      buildDependencies: {
        // 2. Add your config as buildDependency to get cache invalidation on config change
        config: [__filename]
    
        // 3. If you have other things the build depends on you can add them here
        // Note that webpack, loaders and all modules referenced from your config are automatically added
      }
    }

    缓存文件存储在 node_modules/.cache/webpack 或 .pnp/.cache/webpack 中。

    Named Chunk IDs

    在 Webpack5 中开发模式将默认启用全新的 Chunk ID 命名算法,提高 Chunk 名称的可读性。Module ID 由其相对的上下文路径决定,Chunk ID 由其内容决定。

    也可以通过下面的配置开启或禁用新的命名算法:

    • 开启:optimization: { chunkIds: 'named' }

    • 关闭:optimization: { chunkIds: 'natural' }

    Deterministic Chunk and Module IDs

    为了帮助长期缓存(long term caching),Webpack 5 增加了新的算法。新算法会以确定的方式为 Module、Chunk 分配一个非常短(3~4 个字符)的数字 ID。因此,对于没有发生变化的 Module 或 Chunk,它们对于的 ID 也不会发生变化,仍然可以被浏览器缓存,提高资源加载的性能。

    • 开启:optimization: { chunkIds: 'deterministic' }

    • 关闭:optimization: { chunkIds: 'size' }

    Tree-shaking Optimize

    Webpack 5 可以追踪分析嵌套模块的再输出,移除未使用的代码。

    下面代码中编译后 b 将会被移除:

    // inner.js
    export const a = 1;
    export const b = 2;
    
    // module.js
    import * as inner from "./inner";
    export { inner }
    
    // user.js
    import * as module from "./module";
    console.log(module.inner.a);

    另外,Webpack 5 新增了优化选项 optimization.innerGraph,可以分析模块内部输入、输出的依赖关系,来判断哪些代码未使用。

    import { something } from "./something";
    
    function usingSomething() {
      return something;
    }
    
    export function test() {
      return usingSomething();
    }

    上面的代码,如果 test() 未被使用,那么 ./something 将会在 Tree-shaking 过程中被移除。

    Improved Code Generation

    Webpack 4 最终编译生成的代码对应的版本是 ES5,Webpack 5 中可以指定编译后的代码版本为 ES5 或 ES6/ES2015。

    output: { ecmaVersion: 5 | 2015 }


    其实es6,目前大部兼容性还是不太好。未来可期

    SplitChunks and Module Sizes

    Webpack 支持 splitChunks 给不同的文件类型设定文件最小、最大的拆分限制条件。

    minSize: {
        javascript: 30000,
        style: 50000,
    }

    这是主要功能

    webpack4升级到webpack5

    To v5 from v4,官方文档:https://webpack.js.org/migrate/5/

    npm install webpack@next --dev

    配置还是需要修改的

    更新的配置项

    以下配置需要更新

    • optimization.hashedModuleIds: true ↦ optimization.moduleIds: 'hashed'

    • optimization.namedChunks: true ↦ optimization.chunkIds: 'named'

    • optimization.namedModules: true ↦ optimization.moduleIds: 'named'

    • NamedModulesPlugin ↦ optimization.moduleIds: 'named'

    • NamedChunksPlugin ↦ optimization.chunkIds: 'named'

    • HashedModulesPlugin ↦ optimization.moduleIds: 'hashed'

    • optimization.occurrenceOrder: true ↦ optimization: { chunkIds: 'total-size', moduleIds: 'size' }

    • optimization.splitChunks.cacheGroups.vendors ↦ optimization.splitChunks.cacheGroups.defaultVendors

    • Compilation.entries ↦ Compilation.entryDependencies

    • serve ↦ serve is removed in favor of DevServer

    清除的配置项

    • Consider removing optimization.moduleIds and optimization.chunkIds from your webpack configuration. The defaults could be better, because they support long term caching in production mode and debugging in development mode.

    • When using [hash] placeholder in webpack configuration, consider changing it to [contenthash]. It is not the same, but proven to be more effective.

    • If you are using Yarn's PnP and the pnp-webpack-plugin, we have good news: it is supported by default now. You have to remove it from the configuration.

    • If you are using IgnorePlugin with a regular expression as argument, it takes an options object now: new IgnorePlugin({ resourceRegExp: /regExp/ }).

    Reconsider optimization.splitChunks:

    • It's recommended to use either the defaults or optimization.splitChunks: { chunks: 'all' }.

    • When using HTTP/2 and long term caching, set optimization.splitChunks: { chunks: 'all', maxInitialRequests: 30, maxAsyncRequests: 30, maxSize: 100000 }.

    • When using a custom configuration, replace name with idHint.

    • It was possible to turn off the defaults by setting optimization.splitChunks: { default: false, vendors: false }. We don't recommend doing this, but if you really want to get the same effect in webpack 5: optimization.splitChunks: { default: false, defaultVendors: false }.


    高级进阶

    CDN配置

    // webpack.config.jsconst path = require('path');{
      entry: {
        main: './src/index.js',
        sub: './src/sub.js'
      },
      output: {
        publicPath: 'http://cdn.example.com'
        filename: '[name].js',
        path: path.resolve(__dirname, 'dist')
      }}

    写入到http://cdn.example.com/main.js, http://cdn.example.com/sub.js

    Webpack5 模块联邦让 Webpack 达到了线上 Runtime 的效果,让代码直接在项目间利用 CDN 直接共享,不再需要本地安装 Npm 包、构建再发布了!

    我们知道 Webpack 可以通过 DLL 或者 Externals 做代码共享时 Common Chunk,但不同应用和项目间这个任务就变得困难了,我们几乎无法在项目之间做到按需热插拔。

    模块联邦是 Webpack5 新内置的一个重要功能,可以让跨应用间真正做到模块共享,所以这周让我们通过 webpack-5-module-federation-a-game-changer-in-javascript-architecture 这篇文章了解什么是 “模块联邦” 功能。

    • NPM 方式共享模块:常的代码共享需要将依赖作为 Lib 安装到项目,进行 Webpack 打包构建再上线

    • UMD 方式共享模块:真正 Runtime 的方式可能是 UMD 方式共享代码模块,即将模块用 Webpack UMD 模式打包,并输出到其他项目中。

    • 微前端方式共享模块:微前端就是要解决多项目并存问题,多项目并存的最大问题就是模块共享,不能有冲突。

      • 子应用独立打包,模块更解耦,但无法抽取公共依赖等。

      • 整体应用一起打包,很好解决上面的问题,但打包速度实在是太慢了,不具备水平扩展能力。

    讨论地址是:精读《Webpack5 新特性 - 模块联邦》 · Issue #239 · dt-fe/weekly

    PWA 打包配置

    渐进式网络应用程序(Progressive Web Application - PWA),是一种可以提供类似于原生应用程序(native app)体验的网络应用程序(web app)。PWA 可以用来做很多事。其中最重要的是,在离线(offline)时应用程序能够继续运行功能。这是通过使用名为 Service Workers 的网络技术来实现的 添加 workbox-webpack-plugin 插件,并调整 webpack.config.js 文件:

    npm install workbox-webpack-plugin --save-dev

    webpack.config.js

    const path = require('path');
    const HtmlWebpackPlugin = require('html-webpack-plugin');
    const CleanWebpackPlugin = require('clean-webpack-plugin');
    const WorkboxPlugin = require('workbox-webpack-plugin');
    
    module.exports = {
     entry: {
          app: './src/index.js',
          print: './src/print.js'
        },
      plugins: [
        new CleanWebpackPlugin(['dist']),
        new HtmlWebpackPlugin({
         title: 'Output Management'
         title: 'Progressive Web Application'
       })
       }),
       new WorkboxPlugin.GenerateSW({
         // 这些选项帮助 ServiceWorkers 快速启用
         // 不允许遗留任何“旧的” ServiceWorkers
         clientsClaim: true,
         skipWaiting: true
       })
      ],
      output: {
          filename: '[name].bundle.js',
          path: path.resolve(__dirname, 'dist')
        }
      };

    注册 Service Worker

    import _ from 'lodash';
    import printMe from './print.js';
    
    if ('serviceWorker' in navigator) {
       window.addEventListener('load', () => {
         navigator.serviceWorker.register('/sw.js').then(registration => {
           console.log('SW registered: ', registration);
         }).catch(registrationError => {
           console.log('SW registration failed: ', registrationError);
         });
       });
    }

    现在来进行测试。停止服务器并刷新页面。如果浏览器能够支持 Service Worker,你应该可以看到你的应用程序还在正常运行。然而,服务器已经停止了服务,此刻是 Service Worker 在提供服务。


    参考文章:

    了解 Webpack 5 https://www.hexuanzhang.com/2413384094.html

    精读《Webpack5 新特性 - 模块联邦》 https://zhuanlan.zhihu.com/p/115403616

    webpack5新特性总结 https://blog.csdn.net/webofrxy/article/details/94436780

    webpack5快发布了,你还没用过4吗? https://zhuanlan.zhihu.com/p/99339368?from_voters_page=true



    转载本站文章《webpack5新功能展望》,
    请注明出处:https://www.zhoulujun.net/html/tools/Bundler/webpack/2020_0813_8544.html