使用Webpack和Babel的ES6动态导入

时间:2018-02-16 13:18:39

标签: javascript webpack ecmascript-6 babeljs es6-modules

我一直在使用Webpack作为我的ES6 JS项目,并且在我开始使用动态导入之前一直很顺利。

我的工作原理(router.js):

import { navigo } from "Navigo"; // router
import { clients } from "Controllers/clients.js";

const navigo = new Navigo();

navigo_router.on({
  '/clients': () => {
    clients.init();
  }
});

但是我添加的页面/路线越多,在模块的头部堆积的进口就越多。这是一个相对较大的应用程序,我有很多页面/路由要添加,因此我需要动态加载它们以减少初始页面加载的大小。

因此,在Webpack's documentation for dynamic imports之后,我尝试了以下内容,当调用相对路径时,它会加载控制器模块

import { navigo } from "Navigo"; // router

const navigo = new Navigo();

navigo_router.on({
  '/clients': () => {
    import("Controllers/clients.js").then((clients) => {
      clients.init();
    });
  }
});

但是在我的编辑器中保存它会导致Babel发生错误; 语法错误:'导入'和'导出'可能只出现在顶层,并且在浏览器中测试时未调用clients.init()

经过一番阅读后,我发现我需要Babel plugin来将动态import()转换为require.ensure。所以,我使用以下命令安装了插件:

npm install babel-plugin-dynamic-import-webpack --save-dev

并在我的babel.rc文件

中声明了该插件
{ "plugins": ["dynamic-import-webpack"] }

安装插件后,转换错误消失了,检查我的转换代码我发现动态import()实际上已按预期更改为require.ensure。但现在我在测试时遇到以下浏览器错误:

Error: Loading chunk 0 failed.
Stack trace:
u@https://<mydomain.com>/js/app.bundle.js:1:871
SyntaxError: expected expression, got '<' 0.app.bundle.js:1
Error: Loading chunk 0 failed.

我不明白它为什么用0.app.bundle.js前缀引用0.,所以我检查了我的output / dist文件夹,现在我有一个名为0.app.bundle.js的新文件:

0.app.bundle.js      1,962bytes
app.bundle.js        110,656bytes

我想这个新的捆绑文件是动态导入的模块clients.js

我只添加了动态导入到那条路线,并保留了所有其他路线。因此,在测试期间,我可以查看除了现在抛出上述错误的一条/clients路由之外的所有路由。

我在这一点上完全迷失了,并希望有人可以帮助我超越终点线。什么是新文件0.app.bundle.js以及我应该如何在我的应用程序中使用它/包括它?

我希望我已经清楚地解释了自己,并期待任何回应。

2 个答案:

答案 0 :(得分:3)

我最终设法解决了自己的问题,所以我将分享我在答案中发现的内容。

块文件没有加载的原因是因为Webpack正在查找错误的目录。我在开发人员控制台的“网络”选项卡中注意到,从我的根目录/调用了块文件/模块,而不是在它所属的/js目录中。

根据Webpack的文档,我将以下内容添加到我的Webpack配置文件中:

output: {
  path: path.resolve(__dirname, 'dist/js'),
  publicPath: "/js/", //<---------------- added this
  filename: 'app.bundle.js'
},

据我所知,path适用于Webpack的静态模块,publicPath适用于动态模块。

这使得块加载正确但我还有其他问题需要处理,因为client.init()没有被调用并产生以下错误:

TypeError: e.init is not a function

要解决这个问题,我还必须改变:

import("Controllers/clients.js").then((clients) => {
  clients.init();
});

要:

import("Controllers/clients.js").then(({clients}) => {
  clients.init();
});

请注意箭头函数参数中的花括号。

我希望这有助于其他人。

答案 1 :(得分:0)

要进行调试,您需要执行

import("Controllers/clients.js").then((clients) => {
    console.log(clients);
});

也许正在工作

import("Controllers/clients.js").then((clients) => {
    clients.default.init();
});