使用 webpack4.x 拆分 SPA 应用关键代码以优化页面加载速度并且解决关键的坑

阅读时长 6 分钟读完

随着用户需求的不断增长,单页应用(SPA)的使用也越来越普遍。SPA 的主要特点是在前端路由控制下,使用 Ajax 操作实现页面的动态加载。但是,由于 SPA 原来所有的代码都被打包到一个文件中,因此导致页面初始化速度较慢,用户体验也不佳。

为了解决 SPA 应用的这个问题,我们可以使用 webpack4.x 来拆分 SPA 应用关键代码以优化页面加载速度并且解决关键的坑。

webpack4.x 基础概念

Webpack 是一个开源的前端资源打包工具,它是一个静态模块打包器(module bundler)。Webpack 可以对 JavaScript、CSS、图片等文件进行打包,并输出对应的静态资源文件。Webpack 的最大特点是,它支持代码分割(Code Splitting),也就是说,Webpack 可以将多个 JavaScript 文件打包成不同的 bundle 文件。

要使用 webpack4.x 实现代码分割,需要了解以下几个概念:

  • entry:入口文件,Webpack 从这个文件开始打包。
  • output:输出文件,Webpack 把打包后的资源输出到这个文件中。
  • module:模块,Webpack 把应用中所有依赖的文件打包到模块中。
  • bundle:打包后的文件,Webpack 将所有模块打包成一个 bundle。

代码拆分

为了实现代码分割,我们需要使用 webpack 的 splitChunk 插件。这个插件从 webpack 4.0 开始成为了官方提供的功能。

1. 公共模块拆分

公共模块是指应用中多个模块共用的一个模块。为了避免重复打包,我们可以将这个公共模块拆分出来,打包成一个独立的文件。

-- -------------------- ---- -------
-------------- - -
  ------ -
    ---- ---------------
    ------- --------- ------------
  --
  ------- -
    ----- -------------------- --------
    --------- --------------------
  --
  ------------- -
    ------------ -
      ------------ -
        -------- -
          ----- ----------
          ------- ----------
          ---------- -
        -
      -
    -
  -
--

上面的示例代码中,我们将 reactreact-dom 分别打包成一个独立的文件。其中,vendor 中的内容被打包成 vendor.[hash:8].js 文件,cacheGroups 中的 commons 被打包成 commons.[hash:8].js 文件。

2. 按需加载

在实际的项目中,可能存在一些路由或组件在第一次加载时不需要用到,只有在用户点击或需要时才会加载。这时候,我们就需要按需加载(Dynamic Import)。

Webpack4.x 提供了一个方法来进行按需加载:

上面的代码中,webpackChunkName 是指定生成的 chunk 文件名,"path/to/module" 是一个需要按需加载的文件路径。Webpack 会根据这个文件路径生成一个大小合适的 chunk 文件。

-- -------------------- ---- -------
----- -------- ------- --------------- -
  ----------- - -- -- -
    --------- ----------------- --------- -- ------------
      ------------- -- -
        -----------------------------
      --
      ------------ -- -
        --------------- ----- -------- ----- ------- --- ------------
      ---
  --

  -------- -
    ------ -
      -----
        -------- ---------
        ------- ------------------------------- ----------------
      ------
    --
  -
-

上面的示例代码中,我们按需加载了 ./SubPage 组件,生成了一个名为 subpage 的 chunk 文件。

在实际使用中,可能会遇到一些坑。下面列举了一些常见的问题及其解决方案。

1. 使用react-router打包时,出现重复打包问题

由于 react-router 会 default export 一个 Router 组件,而这个组件只有一个路径,这导致 Webpack 会将这个组件以路径 default 加载进多个 bundle 中。为了解决这个问题,可以使用 CommonJS 语法来导出数据。

-- -------------------- ---- -------
----- ------------ - -- -- -
  ------ -
    --------
      --------
        ------ ----- -------- ---------------- --
        ------ ------------- ----------------- --
      ---------
    ---------
  --
--

------ ------- -------------

2. 使用Antd时,出现问题

Antd 的按需加载需要使用 babel-plugin-import 插件,该插件用于按需加载组件代码和样式。由于此插件会与 webpack4.x 自带的代码压缩工具冲突,需要将 webpack4.x 自带的代码压缩工具禁用。可以在项目根目录下添加一个 babel.config.js 文件,并将项目执行语法转换的内容稍稍修改即可:

-- -------------------- ---- -------
-------------- - --- -- -
  -- ---
  ------ -
    -------- ---
    -------- -
      -
        ---------
        -
          ------------ -------
          ----------------- -----
          ------ -----
        -
      -
    -
  --
--

3. 自定义chunk的名称不生效

如果按需加载不指定名称,默认会生成一个魔法注释,比如:webpackChunkName: "subpage" + "." + hash。如果指定名称,可以在请求的时候,对应地命名,比如:

注意:我的项目是使用 create-react-app 创建的,会有自己的 react-scripts,需要 eject 后才能自定义配置。

总结

使用 webpack4.x 拆分 SPA 应用关键代码以优化页面加载速度,可以通过公共模块拆分和按需加载实现。在实践中,可能会遇到重复打包、Antd 及命名无效等常见问题,需要针对性地解决。希望本文能够对你理解 webpack4.x 的代码分割和优化SPA应用速度有所帮助。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64cdf2d1b5eee0b5255e6495

纠错
反馈