vue-cli cdn方式引入Vue模块
文章目录
- vue-cli cdn 方式引入 Vue 模块
- 前言
- 选择 Vue 的 cdn
- 如何引入 cdn ?
- 一手插入
- 一手准备
- 小结 + 打包测试
- 快速配置篇
- FAQ
- 是否需要删除 import Vue 语句?
- cdn 哪里找?
- 兼容性
- 样式表怎么使用第三方 CDN ?
vue-cli cdn 方式引入 Vue 模块
前言
如果你只是想快速配置 cdn,可以直接看快速配置篇。
Chrome 将于不久后默认开启 限制子资源在私有网络的分发 策略,它会导致非 https 协议无法使用第三方外链,这将导致开发环境无法使用 cdn。这个策略我在测试时对 CSS 样式表无效。
这个安全策略开启后,你可能会在未来遇到这个错误:
我当前是 Chrome 91,可以在 Chrome 浏览器的地址栏中输入 chrome://flags/#block-insecure-private-network-requests 来找到这个策略,在未来的版本它会被默认开启,如果你现在主动启用该策略,那么开发环境使用 cdn 你将遇到一个错误:The request client is not a secure context and the resource is in more-private address space \
local`.`
综上,该博客于 2021-07-08 日做了非常大的改动。本来 Vue 也出 3 了,这篇模块也没还没讨论 Vue3 的 cdn 引入方式。
选择 Vue 的 cdn
引入的 vue 文件必须是游览器版本,最少需要 运行时源码,根据你的 Vue 版本不同,选择的文件也不同:
- Vue2 版本的用户选择: vue.runtime.min.js;
- Vue3 版本的用户选择: vue.runtime.global.prod.js。
运行时源码和完整版有什么不同?
运行时源码少了编译器,而完整版有,因为 vue-loader 已经编译了template
,所以不需要再次编译。这意味着运行时源码还要小一点,详见vue2 官方文档 或者 vue3 官方文档。
我使用的是 bootcdn 的运行时压缩模块,体积会更小。切记,使用的 cdn 需要和你的 package.json 中依赖包的版本号相同,以免产生版本 bug。
如何引入 cdn ?
因为开发环境不能安全使用第三方外链,所以第三方 cdn 只能在生产环境中使用。
具体引入方式是在 vue.config.js
中注册 cdn 的模板变量,然后在 public/index.html
中插入。一手准备,一手插入。
一手插入
使用 vue-cli 构建的项目,可以在 项目/public/index.html 的 head 元素中 插入准备好的 cdn 模板。
我的代码如下:
<head><meta charset="utf-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width,initial-scale=1.0" /><link rel="icon" href="<%= BASE_URL %>favicon.ico" /><title>vue-app</title><!-- 这里是插入的 CDN 位置,编写下面这行代码即可。 --><%= htmlWebpackPlugin.options.cdns %>
</head>
这里使用了 html-webpack-plugin 插件的模板参数,你可以通过此插件准备一些参数插入到这个模板中。
可以看到,我们插入了 <%= htmlWebpackPlugin.options.cdns %>
参数,这就是我们需要准备的 cdn 模板。
诸如
<%= %>
这类语法是 EJS 模板语法,想要详细了解可以看看它的 中文文档。
一手准备
来到 项目/vue.config.js
文件,如果没有就创建。
准备分两步:
设置外部依赖:在打包时忽略已经用 cdn 引入的模块。
添加模板参数:准备插入的 cdn 资源元素。
以下代码中,Moment.js 和 Vue3 就是用了 cdn 来引入,并且在打包时忽略这两个模块:
/** @file vue.config.js */module.exports = {chainWebpack: (config) => {// 只在生产环境使用 cdnif (process.env.NODE_ENV === "production") {// 忽略 vue 和 moment 这两个模块config.externals({vue: "Vue",moment: "moment",});// 修改 HtmlWebpackPlugin 插件参数,植入 cdns 这个模板参数,值为 Vue3 和 Moment.js 的 cdn 链接config.plugin("html").tap((args) => {args[0].cdns = `<script src="https://cdn.bootcdn.net/ajax/libs/vue/3.1.2/vue.runtime.global.prod.min.js" crossorigin="anonymous"></script><script src="https://cdn.bootcdn.net/ajax/libs/moment.js/2.29.1/moment.min.js" crossorigin="anonymous"></script>`;return args;});}},
};
其中:
config.externals
用于配置 外部扩展,其作用是不打包使用外部引入的扩展,也就是 build 的时候不打包这些模块。它的键名和值是有意义的:键名:键名为使用外部扩展的模块。 比如
import VueLib123 from "vue"
这句话,模块from "vue"
是不变的,模块名就是这个就是键名。值:值就是使用 cdn 后,这个模块在全局上的引用。 比如 Vue 使用 cdn 引入后,全局上使用
Vue
变量来访问,那么外部扩展的值就是 Vue。
config.plugin("html").tap
用于修改 HtmlWebpackPlugin 这个插件的参数,这里插入一个cdns
参数,所以在public/index.html
中可以使用<%= htmlWebpackPlugin.options.cdns %>
来访问这个参数。
- 上述代码使用的 Webpack 配置方式是 链式调用,因为涉及修改插件参数,无法使用 简单配置。
- 我在 script 元素中设置了 crossorigin 属性,取消了用户凭证传递,详见 CORS settings attributes 。
- 如果你想更安全的使用第三方 cdn ,那么推荐你使用 SRI。
小结 + 打包测试
注意:源代码只是改了 “项目/public/index.html” 文件和配置了 vue.config.js,没有修改其他代码。此方法并不会在开发环境中使用 cdn,具体原因参考第一节前言。
测试代码的 package.json
依赖为:
{"dependencies": {"core-js": "^3.6.5","moment": "^2.29.1","vue": "^3.0.0"}
}
其中 moment
和 vue
使用了 cdn 引入。
不使用 cdn 的打包情况(注释掉 vue.config.js 添加的代码就可测试):
warningwebpack performance recommendations:
You can limit the size of your bundles by using import() or require.ensure to lazy load some parts of your application.
For more info visit https://webpack.js.org/guides/code-splitting/File Size Gzippeddist\js\chunk-vendors.50f67bb1.js 379.14 KiB 110.63 KiBdist\js\app.d4b48aed.js 6.54 KiB 2.45 KiBImages and other types of assets omitted.DONE Build complete. The dist directory is ready to be deployed.INFO Check out deployment instructions at https://cli.vuejs.org/guide/deployment.htmlDone in 5.03s.
上来直接报一个包太大警告,这项目还什么都没写,就是在 App.vue
里面引入了 Moment.js。
其中 chunk-vendors
为 379.14 KB,包含了 core-js
、moment
和 vue
三个模块。
使用 cdn 的打包情况:
DONE Compiled successfully in 720ms 下午2:52:47File Size Gzippeddist\js\chunk-vendors.20dbb2c7.js 24.82 KiB 9.06 KiBdist\js\app.08fbc8da.js 2.02 KiB 0.99 KiBImages and other types of assets omitted.DONE Build complete. The dist directory is ready to be deployed.INFO Check out deployment instructions at https://cli.vuejs.org/guide/deployment.htmlDone in 3.49s.
此时 chunk-venders 降到 24KB,只剩一些关于 core-js
的依赖了。
小结:
这种打包方式只是阐述基本实现方式,如果你觉得比较麻烦,可以看最后一节快速配置篇。
如果想继续优化打包,建议了解异步路由,异步加载等,谨慎使用 require.context
。
快速配置篇
我自己也没那么多时间每次去查怎么配置,所以直接封装了一个函数。
- 首先,在
public/index.html
的head
元素里面添加下面这行代码用来插入 cdn。
<%= htmlWebpackPlugin.options.cdns %>
- 接着新建一个文件
useCDNs.js
在任意位置,我放到了根路径/webpack/useCDNs.js
中。新建后复制以下代码粘贴进去即可,注释不想要可以删掉。
/** @file useCDNs.js *//** @typedef {string} ModuleName 模块名 */
/** @typedef {string} ModuleRefer 模块在全局的引用 */
/** @typedef {string} ElementTem 元素模板 */
/** @typedef {{mod:ModuleName;refer:ModuleRefer;el:ElementTem}} CDNItem cdn 项目 *//*** cdn 使用函数。** 此函数可以在指定开发环境中,指定某些模块作为外部依赖出现,并把准备好的第三方 cdn 模板以 `cdns` 参数通过 HtmlWebpackPlugin 插件插入到 `public/index.html` 文件中。* 你可以在 `public/index.html` 中使用 ejs 语法 <%= htmlWebpackPlugin.options.cdns %> 来插入准备好的 cdn。** @param {import('webpack-chain')} config webpack-chain 实例* @param {CDNItem[]} cdns 传入需要使用的 cdn 数组* @param {string} env 什么环境下使用 cdn ,默认生产环境*/
module.exports = function useCDNs(config, cdns = [], env = "production") {if (process.env.NODE_ENV !== env) return;config.externals(cdns.reduce((prev, v) => {prev[v.mod] = v.refer;return prev;}, {}));config.plugin("html").tap((args) => {args[0].cdns = cdns.map((v) => v.el).join("");return args;});
};
- 最后在
vue.config.js
中使用如下方式调用:
/** @file vue.config.js */const useCDNs = require("./webpack/useCDNs");module.exports = {chainWebpack: (config) => {useCDNs(config, [{mod: "vue",refer: "Vue",el: `<script src="https://cdn.bootcdn.net/ajax/libs/vue/3.1.2/vue.runtime.global.prod.min.js"></script>`,},{mod: "moment",refer: "moment",el: `<script src="https://cdn.bootcdn.net/ajax/libs/moment.js/2.29.1/moment.min.js" crossorigin="anonymous"></script>`,},]);},
};
其中,mod
和 refer
对应了外部扩展的模块名和引用名,el
为 cdn 元素。
关于 useCDNs
详细使用参考原文件,注释已经写满了。
FAQ
是否需要删除 import Vue 语句?
不用删除,也不能删除。
因为本文方法只是配置了生成环境使用 cdn,开发环境使用的还是 node_moduels
中的本地包,删了开发环境就 GG。
cdn 哪里找?
以前我使用的是 bootcdn,但这家前年过年前后崩过一次,后来没怎么使用。
你可以使用 UNPKG,这个是和 npm 库直接关联的。
或者 JSDELIVR,老牌 cdn 有保障,还支持 SRI。
兼容性
vue-cli3 和 vue-cli4 都兼容这种配置方式。
样式表怎么使用第三方 CDN ?
首先,样式表是没有外部扩展的;其次,文章前言中提到的限制子资源策略对 CSS 并无作用。
如果你想让 CSS 使用 CDN,可以直接在 public/index.html
文件的 head
元素中直接引入即可,开发环境和生产环境都有效。
需要说的是,因为样式表没有外部扩展。如果全搬上文中引入 JS 的方式,就需要删除项目中的 CSS 引入,不然在生产环境中就会存在两份样式表。
比如你用了 ElementUI,在项目中你引入了 import "element-ui/lib/theme-chalk/index.css"
,如果在 public/index.html
中再引入一次,或者在 vue.config.js
中再添加一次,都会造成二次引入。虽然多次引入对渲染结果无影响,但这样做会让浏览器产生额外的样式计算,损耗性能。
vue-cli cdn方式引入Vue模块相关推荐
- Vue以CDN方式调用Swiper轮播异常
Vue以CDN方式调用Swiper轮播异常 参考文章: (1)Vue以CDN方式调用Swiper轮播异常 (2)https://www.cnblogs.com/Tylerrrkd/p/9165886. ...
- cdn方式引入外部的js库
cdn方式引入外部的js库 1.引入jQuery <!-- 引入jQuery使用cdn的方式引入jQuery --> <script src="http://lib.sin ...
- vue cli 3 升级到 vue cli 4 方法步骤及升级点总结
vue cli 3 升级到 vue cli 4 方法步骤及升级点总结 官方升级英文文档,中文文档相对滞后. 简介:vue cli 4 官方已经更新有一段时间了,现在是4.0.5 版本,看了官方文档大概 ...
- 使用Yarn全局安装@vue/cli,无法执行vue命令的解决方案
使用Yarn全局安装@vue/cli,无法执行vue命令的解决方案 使用Yarn全局安装@vue/cli,无法执行vue命令的解决方案 使用Yarn全局安装@vue/cli,无法执行vue命令的解决方 ...
- 前端 cdn 方式使用 Vue + element-ui
一.引入资源 <script src="https://unpkg.com/vue@2.7.10/dist/vue.min.js"></script> &l ...
- 原声html中怎么加载vue文件,HTML文件引入Vue开发
HTML文件引入Vue开发 页面标题 {{text}} {{item.text}} 点击事件 @click {{text}} 添加文本使用两个大括号{{文本}} img标签中src前面得加冒号 new ...
- vue引入cdn Vue 优化Vue引入 cdn vue cdn Vue优化引入CDN vue 项目 CDN优化
vue引入cdn Vue 优化Vue引入 cdn vue cdn Vue优化引入CDN vue 项目 CDN优化 未引入 CDN前 main.js 更改CDN方式引入 在 vue.config 中引入 ...
- vue main.js中引入js_手把手教你深入Vue3.0(Vue-cli4)项目打包性能优化实践
记录了自己的博客在禁用缓存的情况下,从八九秒加载时间到最终985ms的优化实践,开启缓存的情况下能达到138ms的访问速度 本人的个人博客采用的是Vue-cli4.1.2 + typescript构建 ...
- vue cli 4 多环境_Vue 笔记整理19
19.1 vue-cli起步 19.1.1 什么是vue-cli Vue CLI 是一个基于 Vue.js 进行快速开发的完整系统,提供: - 通过 @vue/cli 搭建交互式的项目脚手架. - 通 ...
最新文章
- vivado的综合与实现策略怎样设置
- android listview分页显示,Android应用中使用ListView来分页显示刷新的内容
- CnPack 使用的组件命名约定
- linux mysql 知乎_在 Linux 上安装 MariaDB 或 MySQL | Linux 中国
- HDU 1573: X问题
- GMGridView cell button
- 类路径是什么意思_多播是什么意思 多播介绍【详解】
- java文件出现字符串_找出三个文本文件中都出现的字符串,并输出到一个文本文件(菜鸟求救)...
- 导致溢出_1篇文章搞清楚8种JVM内存溢出(OOM)的原因和解决方法
- Linux的Nginx三:类型|特点
- 全志A33-gpio驱动程序
- Java学习----方法的重载
- DHCP服务器如何检测穿过中继代理的IP地址冲突(gratuitous ARP肯定是不行的)
- 线程池是如何重复利用空闲线程的?
- Linux下mongodb用户管理和设置远程登陆
- 广西建工OA系统office插件显示问题解决方案
- 2023王道数据结构P40题二.1,关于是否会断链的问题
- ubuntu18下载utuntu18镜像
- 《读万卷书行万里路》国画大家罗建泉写生艺术
- 上位机与下位机交互--让socket不死
热门文章
- 矽杰微 X8M2101 单片机
- 第3章 软件测试方法--基于直觉和经验的方法
- 实例简述Spring AOP之对AspectJ语法的支持
- 报错Unknown custom element: <组件名> - did you register the component correctly?的原因及解决办法
- 关于中断的分类和优先级(优先级由高到低排序)
- Daily record-August
- Python内置函数os模块shutil模块
- orb-slam2 从单目开始的简单学习(7):Optimizer
- Jackson 数据类型转换(使用JavaType)
- php 获取必应图片信息,PHP自动获取必应今日美图