为什么 ES6 模块导入表达式不适用于资产文件夹中具有某些路径参数的 json 文件?
Why does the ES6 module import expression not work for json files in assets folder with some path arguments?
我遇到了一个似乎不合逻辑的 ES6 导入情况,我想知道为什么以下导入在 Vue.js SFC 的方法中不起作用:
const fullContentFile = '@/assets/rules/rules.json'
import(fullContentFile).then(data => console.log('data 8: ', data))
它在浏览器的控制台上抛出以下错误:
Uncaught (in promise) Error: Cannot find module '@/assets/rules/rules.json'
at eval (eval at ./src/components/staboqwi lazy recursive (app.js:2117), <anonymous>:5:11)
我重现该失败的项目设置:
vue create import-issue
(创建一个 Vue.js 项目并接受默认值)
- 创建文件:
src/assets/rules/rules.json
,内容如下:
[1,2,3,4,5]
- 在App.vue中添加以下
created()
方法:
created() {
// The first three imports work always:
import('@/assets/rules/rules.json').then(data =>
console.log('data 1: ', data)
)
const file = 'rules'
import('@/assets/rules/' + file + '.json').then(data =>
console.log('data 2: ', data)
)
const fileName = 'rules.json'
import('@/assets/rules/' + fileName).then(data =>
console.log('data 3: ', data)
)
// The next two imports break compilation if used within htmlcars project
const fileName2 = 'rules/rules.json'
import('@/assets/' + fileName2).then(data =>
console.log('data 4: ', data)
)
const fileName3 = 'assets/rules/rules.json'
import('@/' + fileName3).then(data => console.log('data 5: ', data))
// Those imports don't work:
const contentFile = '/assets/rules/' + file + '.json'
import('@' + contentFile).then(data => console.log('data 6: ', data))
const atContentFile = '@/assets/rules/' + file + '.json'
import(atContentFile).then(data => console.log('data 7: ', data))
const fullContentFile = '@/assets/rules/rules.json'
import(fullContentFile).then(data => console.log('data 8: ', data))
},
正如您从导入的变体中看到的那样,唯一的区别是作为字符串提供给路径参数的内容以及存储在 const/variable.
中的内容
我确实花了 2 个晚上试图在 Google 和 Whosebug 上找到答案。也许比我有更多 javascript 背景的人可以解释最后三个导入与之前的导入相比有什么问题。
一个有趣的副作用是,如果将 create()
方法添加到其 App.vue
文件中,则第 4 次和第 5 次导入会中断 htmlcars 项目的编译(不要忘记添加 src/assets/rules/rules.json
)。如果注释掉项目将构建。这是为什么?导入与编译失败的 scss 文件完全无关。
您需要注意的事实是,当今常见的 JS 项目(包括 Vue)中的 import()
语句是在 构建时由 Webpack 处理的,而不仅仅是在运行时
在构建时,Webpack 需要知道导入了哪个文件,以便它可以在运行时使用它(transpile JS、pre-process SCSS 等)。但是因为这个导入是动态的并且 Webpack 不能执行你的代码,它不可能知道传入 import()
的参数到底意味着什么 。它只能解析代码并做出猜测——“这里可以导入哪个文件?” (根据你的文件系统的内容)
因此,从“JavaScript 执行”的角度来看示例和比较案例是没有意义的,因为什么有效,什么无效最终取决于 Webpack 解析内部表达式的能力 ()
并做出正确的猜测...
在 Webpack 的文档中有更多相关信息 - Dynamic expressions in import()
我遇到了一个似乎不合逻辑的 ES6 导入情况,我想知道为什么以下导入在 Vue.js SFC 的方法中不起作用:
const fullContentFile = '@/assets/rules/rules.json'
import(fullContentFile).then(data => console.log('data 8: ', data))
它在浏览器的控制台上抛出以下错误:
Uncaught (in promise) Error: Cannot find module '@/assets/rules/rules.json'
at eval (eval at ./src/components/staboqwi lazy recursive (app.js:2117), <anonymous>:5:11)
我重现该失败的项目设置:
vue create import-issue
(创建一个 Vue.js 项目并接受默认值)- 创建文件:
src/assets/rules/rules.json
,内容如下:
[1,2,3,4,5]
- 在App.vue中添加以下
created()
方法:
created() {
// The first three imports work always:
import('@/assets/rules/rules.json').then(data =>
console.log('data 1: ', data)
)
const file = 'rules'
import('@/assets/rules/' + file + '.json').then(data =>
console.log('data 2: ', data)
)
const fileName = 'rules.json'
import('@/assets/rules/' + fileName).then(data =>
console.log('data 3: ', data)
)
// The next two imports break compilation if used within htmlcars project
const fileName2 = 'rules/rules.json'
import('@/assets/' + fileName2).then(data =>
console.log('data 4: ', data)
)
const fileName3 = 'assets/rules/rules.json'
import('@/' + fileName3).then(data => console.log('data 5: ', data))
// Those imports don't work:
const contentFile = '/assets/rules/' + file + '.json'
import('@' + contentFile).then(data => console.log('data 6: ', data))
const atContentFile = '@/assets/rules/' + file + '.json'
import(atContentFile).then(data => console.log('data 7: ', data))
const fullContentFile = '@/assets/rules/rules.json'
import(fullContentFile).then(data => console.log('data 8: ', data))
},
正如您从导入的变体中看到的那样,唯一的区别是作为字符串提供给路径参数的内容以及存储在 const/variable.
中的内容我确实花了 2 个晚上试图在 Google 和 Whosebug 上找到答案。也许比我有更多 javascript 背景的人可以解释最后三个导入与之前的导入相比有什么问题。
一个有趣的副作用是,如果将 create()
方法添加到其 App.vue
文件中,则第 4 次和第 5 次导入会中断 htmlcars 项目的编译(不要忘记添加 src/assets/rules/rules.json
)。如果注释掉项目将构建。这是为什么?导入与编译失败的 scss 文件完全无关。
您需要注意的事实是,当今常见的 JS 项目(包括 Vue)中的 import()
语句是在 构建时由 Webpack 处理的,而不仅仅是在运行时
在构建时,Webpack 需要知道导入了哪个文件,以便它可以在运行时使用它(transpile JS、pre-process SCSS 等)。但是因为这个导入是动态的并且 Webpack 不能执行你的代码,它不可能知道传入 import()
的参数到底意味着什么 。它只能解析代码并做出猜测——“这里可以导入哪个文件?” (根据你的文件系统的内容)
因此,从“JavaScript 执行”的角度来看示例和比较案例是没有意义的,因为什么有效,什么无效最终取决于 Webpack 解析内部表达式的能力 ()
并做出正确的猜测...
在 Webpack 的文档中有更多相关信息 - Dynamic expressions in import()