如何在httpVueLoader加载的Vue文件中正确导入ES6模块?
问题结论
你当前的写法不可行,核心原因有两点:
httpVueLoader默认的执行逻辑不支持script标签顶层的ES模块import语句:它拉取.vue文件后,会把script部分的代码作为普通经典脚本包裹后通过new Function()执行,不会识别你加的type="module"属性切换到模块环境,顶层写import自然抛出SyntaxError: Cannot use import statement outside a module错误。- 代码同时混用了ES模块规范的
import和CommonJS规范的module.exports,两类模块规范的顶层语法本身不兼容,即使在原生支持ES模块的环境下也会报错。
可落地的实现方案
方案1:全局预加载(最适配无编译场景,稳定性最高)
直接在入口HTML文件中提前加载urlJoin并挂载到全局,所有.vue组件不需要单独导入,直接调用全局变量即可。
入口HTML示例代码:
<!-- 引入Vue和httpVueLoader --> <script src="https://unpkg.com/vue@2/dist/vue.js"></script> <script src="https://unpkg.com/http-vue-loader"></script> <!-- 提前加载urlJoin挂到全局 --> <script type="module"> import urlJoin from 'https://cdn.skypack.dev/url-join'; window.urlJoin = urlJoin; </script> <script> new Vue({ el: '#app', components: { 'demo-component': httpVueLoader('demo-component.vue') } }) </script>
.vue组件内直接使用即可,不需要写import:
module.exports = { methods: { generateUrl() { return urlJoin('/api', 'user', this.userId); } } }
方案2:组件内动态导入(不需要修改入口文件)
利用ES规范支持的动态import()语法(该语法可在普通脚本环境中使用,返回Promise),在组件内部异步加载模块即可,不需要在代码顶层写import。
组件内script示例代码:
module.exports = { data() { return { urlJoin: null } }, async created() { // 动态加载ES模块,注意取default导出 this.urlJoin = (await import('https://cdn.skypack.dev/url-join')).default; }, methods: { generateUrl() { if (!this.urlJoin) return ''; return this.urlJoin('/api', 'user', this.userId); } } }
如果需要保证组件渲染前模块加载完成,可以直接导出异步组件配置:
module.exports = (async () => { const urlJoin = (await import('https://cdn.skypack.dev/url-join')).default; return { data() { return { userId: 1 } }, methods: { generateUrl() { return urlJoin('/api', 'user', this.userId); } } } })();
方案3:使用支持ESM的httpVueLoader版本(不推荐,兼容性一般)
部分新版本的httpVueLoader支持识别script标签的type="module"属性,你可以把组件改为纯ES模块写法,去掉module.exports改用export default,示例:
<template> <!-- 组件模板内容 --> </template> <script type="module"> import urlJoin from 'https://cdn.skypack.dev/url-join'; export default { methods: { generateUrl() { return urlJoin('/api', 'user', this.userId); } } } </script>
注意:该方案依赖CDN返回正确的CORS响应头,部分场景下会因为跨域问题加载失败,稳定性不如前两个方案。
内容的提问来源于stack exchange,提问作者Milano
相关产品推荐
相关产品推荐

