作者:admin,发布日期:2021-02-06
阅读:19814;评论:14

在vite运行build时,默认会把所有的库文件合并到一个大文件中,产生一个打包后的js文件,其中会包含各种库文件,会导致最后打包完成后的文件过大,同时减慢打包速度,这时可以把库文件代码使用cdn访问,加快打包和网页打开速度。

首先需要确认的是,vite在开发时使用的是自己的一套机制,也就是将代码转换成浏览器原生可以使用的type="module",然后让浏览器的js引擎去直接运行js,不再需要使用构建工具打包,所以可以做到秒开。而vite的编译使用的是另外一个开源的包rollup,这也是这篇文章的主角,而且需要注意的是,开发时dev server是不会去使用cdn的代码的,只会引用我们安装的node_modules内部的代码。

但是这个时候又出现问题了,搞定这些问题前前后后花了我大半天的时间,终于功夫不负有心人,搞定了。

使用rollup自带的ouput.globals

首先参考的是vite用户在github的一条issues,其中尤大提到了rollupOptions.external这个东西,然后我参考了vite的文档,文档中指向了rollup的配置。

Snipaste_2021-02-06_22-56-33.jpg

跳转之后就可以看到官方的文档的第一条就是说明的external,经过百度查找,我打开了第一篇csdn的文章。

https://blog.csdn.net/qq_29722281/article/details/95596372

内部提到了使用globals来指定全局模块名称,这个地方给的样例代码其实已经有问题了:

20190712105338146.png

新版的rollup更新后,globals选项已经被移动到了output.globals,如果不修改则会发生以下错误:

Unknown input options: globals. Allowed options: acorn, acornInjectPlugins, cache, context, experimentalCacheExpiry, external, inlineDynamicImports, input, manualChunks, moduleContext, onwarn, perf, plugins, preserveEntrySignatures, preserveModules, preserveSymlinks, shimMissingExports, strictDeprecations, treeshake, watch

提示我们globals选项不存在,我们需要将globals放入output中才可以使用。

于是我就按照文档,添加了一个globals选项,同时使用external选项来排除打包。

当时代码是这样的:

external: ["vue"],
output: {
    globals: {
        vue: "Vue",
    },
},

添加完成之后,问题就开始出现了:

rollup Failed to resolve module specifier "vue"

查看打包后的代码可以发现,我们的import代码还是原样import了vue,但是这种语法浏览器其实是解析不了了,因为网页没有node_modules,浏览器也就没有办法去别处找这个包。

就是因为这个问题,前前后后搞了半天,终于在谷歌搜到了一个rollup用户的issue,其中的用户和我具有一样的情况,也就是globals选项无效。

参考下方地址:

https://github.com/rollup/rollup/issues/3188

然后经过一番研究,我才找到了最终的问题(当然我之前也有思考过是不是不支持,但是用其他的插件也是无效):

output.globals only sets the global variable for external imports in IIFE bundles (and UMD bundles when they are used in a script tag), in other formats it has no effect. https://www.npmjs.com/package/rollup-plugin-external-globals is probably what you want.

Ah sorry, I see you found that plugin, is it working for you? There are technical reasons this is not supported in core, mostly because it would need to work very differently for non-IIFE formats, potentially provide larger output after minification, and it is totally unclear how to handle this with UMD.

翻译过来,就是说自带的global只支持iife或者umd打包的库文件,这时候我才恍然大悟,我使用的包都是commonjs打包的(关于各种打包的方式使用大家可以谷歌学习),所以才出现这种问题,其实就是本身不支持(不过经过测试其他方式的好像也不可以,可能就是vite本身的问题吧)。

反正经过这个提示,问题已经大概解决了,我们只需要使用插件就能解决这个问题。

使用rollup-plugin-external-globals插件来解决问题

参考:https://github.com/rollup/rollup/issues/2374

插件地址:https://www.npmjs.com/package/rollup-plugin-external-globals

安装插件

yarn add -D rollup-plugin-external-globals

添加配置

使用方法与上方定义方法几乎相同,传入参数给插件初始化方法就行。

      plugins: [
        commonjs(),
        externalGlobals({
          vue: "Vue",
          "ant-design-vue": "antd",
          moment: "moment",
        }),
      ],

参数对解释:

  • vue - 这里需要和external对应,这个字符串就是(import xxx from aaa)中的aaa,也就是包的名字

  • Vue - 这个是js文件导出的全局变量的名字,比如说vue就是Vue,查看源码或者参考作者文档可以获得

下面是全部vite.config.js,供参考:

import vue from "@vitejs/plugin-vue";
import commonjs from "rollup-plugin-commonjs";
import externalGlobals from "rollup-plugin-external-globals";

/**
 * https://vitejs.dev/config/
 * @type {import('vite').UserConfig}
 */
export default {
  plugins: [vue()],
  build: {
    rollupOptions: {
      external: ["vue", "ant-design-vue", "moment"],
      plugins: [
        commonjs(),
        externalGlobals({
          vue: "Vue",
          "ant-design-vue": "antd",
          moment: "moment",
        }),
      ],
    },
  },
};

在index.html中导入静态文件

修改根目录下的index.html,添加cdn文件:

  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ant-design-vue@2.0.0-rc.9/dist/antd.min.css">
  <script src="https://cdn.jsdelivr.net/npm/vue@3.0.5/dist/vue.global.prod.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/moment@2.29.1/moment.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/ant-design-vue@2.0.0-rc.9/dist/antd.js"></script>

整个文件参考下方:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <link rel="icon" href="/favicon.ico" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ant-design-vue@2.0.0-rc.9/dist/antd.min.css">
  <script src="https://cdn.jsdelivr.net/npm/vue@3.0.5/dist/vue.global.prod.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/moment@2.29.1/moment.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/ant-design-vue@2.0.0-rc.9/dist/antd.js"></script>
  <title>Vite App</title>
</head>

<body>
  <div id="app"></div>
  <script type="module" src="/src/main.js"></script>
</body>

</html>

编译测试

vite中提供了preview,可以供我们预览编译后的结果

yarn run build
yarn run serve

Snipaste_2021-02-06_23-20-31.jpg

打开网页发现原先报错已经不存在,问题解决。

Snipaste_2021-02-06_23-21-02.jpg

你可能感兴趣的文章

评论区

已有14位网友发表了看法:

1L luoyi  2021-05-07 16:21:23 回复
大佬牛逼,这问题困扰了我几天终于解决了
2L 访客  2021-05-20 17:14:42 回复
问一下 main.js js 中在如何写呢
2L admin  2021-05-21 09:33:46 回复
@访客 和原来一样
2L 访客  2022-01-06 16:14:33 回复
@访客 你的问题解决了么?用cdn 形式直接加载组件库么
3L 访客  2022-01-06 16:12:59 回复
main.js 代码如下
import { createApp } from 'vue'
import App from './App.vue'
import './index.css'
createApp(App).mount('#app')
在vue 直接用 ant-design-vue 的组件就不生效报错了,报错如下:
vue.js:8068 [Vue warn]: Failed to resolve component: a-button
If this is a native custom element, make sure to exclude it from component resolution via compilerOptions.isCustomElement.
at
at
这个为什么组件找不到啊?大佬
3L admin  2022-01-10 16:36:23 回复
@访客 https://blog.craftyun.cn/post/231.html
得看这个,建议你加群问,要不然这边回复你也看不到
4L 访客  2022-01-18 14:56:42 回复
大佬,我按你上图使用启动之后报错Failed to resolve module specifier "vue". Relative references must start with either "/", "./", or "../". 这个是咋回事
4L admin  2022-01-19 15:42:24 回复
@访客 用esm试试
4L 访客  2022-04-02 14:45:20 回复
@访客 解决了吗兄弟
5L 访客  2022-02-14 17:16:52 回复
报错了
Uncaught TypeError: Failed to resolve module specifier "vue". Relative references must start with either "/", "./", or "../".
5L 访客  2022-04-01 20:06:33 回复
@访客 解决了吗兄弟
6L 访客  2023-06-19 10:26:57 回复
弄了好几天,也总算是解决了
6L 访客  2023-12-24 15:08:43 回复
@访客 怎么解决的
7L micateam  2023-08-28 21:10:43 回复
23年8月了,这个问题还在 没解决,我在单页编译没事把他编译成umd模式即可,多页不支持umd esm模式它就找不到vue了

发表评论

必填

选填

选填

必填

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。