使用 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 许可协议获得许可。