简体   繁体   English

使用Webpack和Babel的ES6动态导入

[英]ES6 Dynamic Imports using Webpack and Babel

I've been using Webpack for my ES6 JS project and has been going well until I started to play with dynamic imports. 我一直在使用Webpack作为我的ES6 JS项目,并且在我开始使用动态导入之前一直很顺利。

What I had that worked (router.js): 我有什么工作(router.js):

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

const navigo = new Navigo();

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

But the more pages/routes I add, the more imports get stacked up in the head of the module. 但是我添加的页面/路线越多,进口就越多地堆积在模块的头部。 This is a relatively large app and I have a lot of pages/routes to add and therefore I need to load them dynamically to reduce the size of the initial page load. 这是一个相对较大的应用程序,我有很多页面/路由要添加,因此我需要动态加载它们,以减少初始页面加载的大小。

So, following Webpack's documentation for dynamic imports , I tried the following which loads the controller module only when the relative route is called: 因此,按照Webpack的动态导入文档 ,我尝试了以下内容, 只有在调用相对路径时才加载控制器模块:

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

const navigo = new Navigo();

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

But saving this in my editor resulted in a Babel transpiling error; 但是在我的编辑器中保存它会导致Babel发生错误; SyntaxError: 'import' and 'export' may only appear at the top level , and clients.init() is not being called when tested in browser. SyntaxError:'import'和'export'可能只出现在顶层 ,并且在浏览器中测试时没有调用clients.init()

After a bit of reading, I discovered I needed a Babel plugin to transpile dynamic import() to require.ensure . 经过一番阅读后,我发现我需要一个Babel插件来将动态import()require.ensure So, I installed the plugin using the following command: 所以,我使用以下命令安装了插件:

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

And declared the plugin in my babel.rc file 并在我的babel.rc文件中声明了该插件

{ "plugins": ["dynamic-import-webpack"] }

After installing the plugin, the transpiling error disappeared and checking my transpiled code I found that the dynamic import() s has in fact been changed to require.ensure as expected. 安装插件后,转换错误消失了,检查我的转换代码我发现动态import()实际上已按预期更改为require.ensure But now I get the following browser errors when testing: 但是现在我在测试时遇到以下浏览器错误:

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.

I didn't understand why it was referencing 0.app.bundle.js with the 0. prefix, so I checked my output/dist folder and I now have a new file in there called 0.app.bundle.js : 我不明白为什么它引用0.app.bundle.js0.前缀,所以我检查了我的输出/ dist文件夹,我现在有一个名为0.app.bundle.js的新文件:

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

I imagine this new bundled file is the dynamically imported module, clients.js . 我想这个新的捆绑文件是动态导入的模块clients.js

I only added dynamic importing to that one route and have left all the other routes as they were. 我只添加了动态导入到那条路线,并保留了所有其他路线。 So, during testing, I can view all routes except that one /clients route that now throws the above errors. 因此,在测试期间,我可以查看除了现在抛出上述错误的一个/clients路由之外的所有路由。

I'm totally lost at this point and hoped somebody could help push me over the finish line. 我完全迷失在这一点上,并希望有人能帮助我超越终点线。 What is this new file 0.app.bundle.js and how am I supposed to be using it/including it in my application? 什么是这个新文件0.app.bundle.js以及我应该如何在我的应用程序中使用它/包含它?

I hope I've explained myself clearly enough and look forward to any responses. 我希望我已经足够清楚地解释了自己,并期待任何回应。

I managed to fix my own problem in the end, so I will share what I discovered in an answer. 我设法最终解决了自己的问题,所以我将分享我在答案中发现的内容。

The reason the chunk file wasn't loading was because Webpack was looking in the wrong directory for it. 块文件未加载的原因是因为Webpack正在查找错误的目录。 I noticed in the Network tab of my developer console that the the chunk file/module was being called from my root directory / and not in /js directory where it belongs. 我在开发人员控制台的“网络”选项卡中注意到,从我的根目录/调用了块文件/模块,而不是在它所属的/js目录中。

As per Webpack's documentation, I added the following to my Webpack config file: 根据Webpack的文档,我将以下内容添加到我的Webpack配置文件中:

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

From what I understand, path is for Webpack's static modules and publicPath is for dynamic modules. 据我所知, path是Webpack的静态模块, publicPath是动态模块。

This made the chunk load correctly but I also had further issues to deal with, as client.init() wasn't being called and yielded the following error: 这使得块加载正确,但我还有其他问题要处理,因为没有调用client.init()并产生以下错误:

TypeError: e.init is not a function

To fix this, I also had to change: 为了解决这个问题,我还必须改变:

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

To: 至:

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

Note the curly braces in the arrow function parameter. 请注意箭头函数参数中的花括号。

I hope this helps somebody else. 我希望这有助于其他人。

For debugging, you need to do 要进行调试,您需要这样做

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

maybe working 也许工作

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM