跳到内容

使用 Webpack Encore 进行异步代码分割

编辑此页

当您 require/import 一个 JavaScript 或 CSS 模块时,Webpack 会将该代码编译到最终的 JavaScript 或 CSS 文件中。通常,这正是您想要的。但是,如果您只需要在特定条件下使用一段代码呢?例如,如果您想使用 video.js 来播放视频,但只有在用户点击链接后才需要,该怎么办?

1
2
3
4
5
6
7
8
9
10
// assets/app.js

import $ from 'jquery';
// a fictional "large" module (e.g. it imports video.js internally)
import VideoPlayer from './components/VideoPlayer';

$('.js-open-video').on('click', function() {
    // use the larger VideoPlayer module
    const player = new VideoPlayer('some-element');
});

在这个例子中,VideoPlayer 模块及其导入的所有内容都将被打包到最终构建的 JavaScript 文件中,即使实际上可能并不常见有人真正需要它。一个更好的解决方案是使用动态导入:在需要时通过 AJAX 加载代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// assets/app.js

import $ from 'jquery';

$('.js-open-video').on('click', function() {
    // you could start a loading animation here

    // use import() as a function - it returns a Promise
    import('./components/VideoPlayer').then(({ default: VideoPlayer }) => {
        // you could stop a loading animation here

        // use the larger VideoPlayer module
        const player = new VideoPlayer('some-element');

    }).catch(error => 'An error occurred while loading the component');
});

通过像函数一样使用 import(),模块将被异步下载,并且在完成时将执行 .then() 回调。回调的 VideoPlayer 参数将是加载的模块。换句话说,它的工作方式类似于普通的 AJAX 调用!在幕后,Webpack 会将 VideoPlayer 模块打包到一个单独的文件中(例如 0.js),以便可以下载。所有细节都为您处理好了。

{ default: VideoPlayer } 部分可能看起来很奇怪。当使用异步导入时,您的 .then() 回调会传递一个对象,其中实际的模块位于 .default 键上。这样做是有原因的,但它看起来确实很古怪。{ default: VideoPlayer } 代码确保我们想要的 VideoPlayer 模块是从这个 .default 属性中读取的。

有关更多详细信息和配置选项,请参阅 Webpack 文档中的动态导入

这项工作,包括代码示例,均根据 Creative Commons BY-SA 3.0 许可协议获得许可。
目录
    版本