webpack 以字符串变量的形式动态import

问题

webpack推出了动态import,可是我最近使用的时候发现,不能通过变量字符串的形式来异步导入:

import('@/a.js').then(...);  //可以
const str = '@/a.js';
import(str).then(...);  //失败

个人猜想

这是webpack赋予的能力,估计只能在编译阶段使用,在runtime中相关的文件也是以一定的hash乱码命名(目的是为了文件缓存,不同的名称浏览器会重新加载而不是使用旧文件。当然也可以设置http头,但是这也就浪费了webpack的特性了,写一次代码保存,浏览器就得全部更新渲染,浪费时间)。
对于动态变量,相当于直接找其原本的名字,但是装载在浏览器的可能早已经改变。

官方说明

webpack给出了说明

The keyword here is statically. A normal import statement cannot be used dynamically within other logic or contain variables. See the spec for more information and import() below for dynamic usage.

我将原文的链接也post出来了(蓝色部分,可以点击)。原来是webpack采用的es6的import语法,也遵守了es6的规范,规范参考上面的蓝色链接spec。所以直接使用变量是不可以的。

解决

百度了有解决方案,但是没讲为什么。
幸好谷歌解决了,这里有个stack overflow的回答

Fully dynamic statements, such as import(foo), will fail because webpack requires at least some file location information. This is because foo could potentially be any path to any file in your system or project. The import() must contain at least some information about where the module is located, so bundling can be limited to a specific directory or set of files.

简而言之,import()必须至少提供关于模块位置的信息,比如import(`./locale/${languge}.json`),这里提供了位置./locale/,也限定了文件类型json,但是只有位置也可以。
但是,这种混合使用,参杂变量,有一定的坏处:

Every module that could potentially be requested on an import() call is included. For example,import(./locale/${language}.json)will cause every .json file in the ./locale directory to be bundled into the new chunk. At run time, when the variable language has been computed, any file like english.json or german.json will be available for consumption.

潜在的模块,即non-initial module,也就是动态导入的模块,也会形成一个chunk。上面的import(./locale/${language}.json),会将目录./locale/下的所有json文件打包成一个chunk。
在这个例子中,如果说不是很依赖所有的json文件,还是一个个的导入好,不然会形成一个很大的chunk,所以浏览器的内存就得浪费一块位置。
所以,将变量的所有可能值,放入一个对象变量:

 const test={
     'a':()=>import('a.json'),
     'b':()=>import('b.json'),
     //。。。更多代码
 }

这样,单独的json文件就是单独的chunk,只有在引入的时候才被加载,避免了chunk过大的问题。
醉了,看webpackAPI文档发现了这个问题的介绍,详情戳这里

总结

  • 1 可以使用变量,但是得提供位置信息(可以使用位置别名,比如'@/')
  • 2 不推荐使用变量,会造成chunk过大的问题
  • 3 想了想总结2,应该还是有其适用的场景,比如默认界面,默认图片啥的需要提前一起加载。
原文地址:https://www.cnblogs.com/panshaojun/p/14516219.html