- You can call me
Kanno
- I've been busy recently
- Learning
zig
nonzzz / vite-plugin-cdn Goto Github PK
View Code? Open in Web Editor NEWreplace module with CDN. work with vite.
License: MIT License
replace module with CDN. work with vite.
License: MIT License
不使用cdn打包后为
// 导入
const i = e=>(Vue.pushScopeId("data-v-d0fc7832"),
e = e(),
Vue.popScopeId(),
e)
// 使用
const i = Vue.ref();
e.forEach(["1", "2", "3"], ((e,t)=>{
i.value = e
}
));
使用cdn后
// 配置
cdn({
modules: [
{ name: 'lodash', relativeModule: 'lodash.js' }
]
})
// 导入 (正常)
const u = e=>(Vue.pushScopeId("data-v-132f7d04"),
e = e(),
Vue.popScopeId(),
e)
// 使用 (不正常)
__wrapped__.forEach(["1", "2", "3"], ((e,t)=>{}
));
会不会是其他插件问题?cdn插件我已放在最后面
就像:
import VitePluginCdn from 'vite-plugin-cdn';
export default {
plugins: [
VitePluginCdn({
esm: true,
modules: [
{
name: 'vue',
url: 'https://cdn.bootcdn.net/ajax/libs/vue/3.0.2/vue.esm-browser.prod.js',
},
],
}),
],
};
比如 URL 参数我提供个 https://cdn.bootcdn.net/ajax/libs/vue/{{ version }}/vue.esm-browser.prod.js
,然后插件会自动解析 {{ version }}
并改为本地 node_modules
里安装的版本。
自己封装组件库,引用了element-plus,用的unplugin-element-plus自动导入样式,代码编译后,里面有相关代码
import { ElButton } from 'element-plus'
import 'element-plus/es/components/button/style/css'
cdn插件modules加入自己组件,就会报错。
跟踪代码发现是 _import 执行的时候报的这个错误。
重现步骤:
创建一个vite项目,新建 test.cjs 文件,内容如下:
var elementPlus = require('element-plus');
require('element-plus/es/components/button/style/css');
exports.ElButton = elementPlus.ElButton
vite.config.ts 文件里面添加以下代码:
import url from "url";
const modulePath = url.pathToFileURL(
"D:\\cdn\\test.cjs"
);
const _import = new Function("specifier", "return import(specifier)");
const pkg = await _import(modulePath);
运行就会报错:Package subpath './es/components/button/style/css' is not defined by "exports"...
删除 require('element-plus/es/components/button/style/css')就正常了。
cdn({
modules: ["react","axios"],
url: "https://cdnjs.cloudflare.com/ajax/libs/",
}),
// 404
以下设置 期待实现 CDN 对应的 url:
https://cdn-abc.com/[email protected]
"devDependencies": {
"vite-plugin-cdn2": "^1.1.0",
}
cdn.js
import { cdn } from "vite-plugin-cdn2";
// import { cdnjs } from "vite-plugin-cdn2/resolver/cdnjs";
import { defineResolve } from "vite-plugin-cdn2/resolve";
// 方法一: 怎么引入需要 cdn 处理的依赖?
export const myResolve = defineResolve({
name: "resolve:custom",
setup({ extra }) {
const baseURL = "https://cdn-abc.com/";
const { version, name, relativeModule } = extra;
const url = new URL(`${name}/${version}/${relativeModule}`, baseURL);
console.log(url);
return {
url: url.href,
injectTo: "head-prepend",
attrs: {}
};
}
});
方法二:
export function enableCDN(isEnabled) {
console.log("enableCDN", isEnabled);
if (isEnabled === "true") {
return cdn({
// url 可以更换为私有或其他源
// url: "https://cdn.jsdelivr.net/npm/",
// url: "https://unpkg.com/",
url: "https://cdn-abc.com",
// modules: ["vue", "vue-demi", "pinia", "axios", "vant", "vue-router"]
modules: [
{
name: "vue",
relativeModule: "./vue.global.js"
}
]
});
}
}
debug模式
pnpm build
> set DEBUG=vite-plugin-cdn2 & vite build
enableCDN true 15:35:03
vite-plugin-cdn2 start scanning +0ms
vite-plugin-cdn2 scanning done Map(0) {} +969ms
ERROR vite-plugin-cdn2: vue Maximum call stack size exceeded 15:35:04
vite v4.5.0 building for production... 15:35:04
✓ 391 modules transformed. 15:35:08
rendering chunks (3)... vite-plugin-cdn2 start transformIndexHtml +14s
vite-plugin-cdn2 transformIndexHtml Done [] +2ms
rendering chunks (3)... vite-plugin-cdn2 start transformIndexHtml +4s
vite-plugin-cdn2 transformIndexHtml Done [] +0ms
✓ built in 17.54s 15:35:21
In some case. look like axios. It set filed type=module
. So that we can't load it. Because we're using commonjs.
can load it correctly.
cdn({
url: 'https://unpkg.com',
modules: ['vue', 'vue-demi', 'vue-router'],
resolve: (base, { name, version }) => {
return ${base}/${name}@${version}
}
})
打包后为下面所示,是link 标签而不是script标签
<link href="https://unpkg.com/vuexxx...
<link href="https://unpkg.com/vue-demixxx...
<link href="https://unpkg.com/vue-routerxxx...
看源码是判断了下面的返回值后缀是否带.js,只有带了才是script. 但是我不想去带上.js
resolve: (base, { name, version }) => {
return ${base}/${name}@${version}
}
感谢作者的无私付出,有两个小疑问。
[1] 我想在项目中,让element-plus的css能够像在https://www.npmjs.com/package/vite-plugin-cdn-import 这个库中一样cdn加载,如何实现?
[2] 这个库 https://github.com/posva/unplugin-vue-router ,不知道作者清楚不?文件自动路由,但是配合当前vite-plugin-cdn2,即使设置了'vue-router' cdn加载,依旧在打包之后,会把vue-router打包进项目。
项目没有直接安装 vue-demi
,项目基础框架是 vue
+ vue-router
+ pinia
[vite-plugin-cdn] Property name expected type of string but got undefined
file: D:/My Projects/MBDownload/frontend/node_modules/.pnpm/[email protected][email protected]/node_modules/vue-demi/lib/index.mjs
error during build:
TypeError: Property name expected type of string but got undefined
at validate (D:\My Projects\MBDownload\frontend\node_modules\.pnpm\@[email protected]\node_modules\@babel\types\lib\definitions\utils.js:134:13)
at Object.validate (D:\My Projects\MBDownload\frontend\node_modules\.pnpm\@[email protected]\node_modules\@babel\types\lib\definitions\utils.js:188:7)
at validateField (D:\My Projects\MBDownload\frontend\node_modules\.pnpm\@[email protected]\node_modules\@babel\types\lib\validators\validate.js:21:9)
at validate (D:\My Projects\MBDownload\frontend\node_modules\.pnpm\@[email protected]\node_modules\@babel\types\lib\validators\validate.js:15:3)
at validateNode (D:\My Projects\MBDownload\frontend\node_modules\.pnpm\@[email protected]\node_modules\@babel\types\lib\builders\validateNode.js:12:27)
at Object.identifier (D:\My Projects\MBDownload\frontend\node_modules\.pnpm\@[email protected]\node_modules\@babel\types\lib\builders\generated\index.js:411:36)
at scanNamedExportsWithoutSource (D:\My Projects\MBDownload\frontend\node_modules\.pnpm\v[email protected]\node_modules\vite-plugin-cdn2\dist\chunk-WFIYNUVD.js:89:102)
at CodeGen.overWriteExportNamedDeclaration (D:\My Projects\MBDownload\frontend\node_modules\.pnpm\v[email protected]\node_modules\vite-plugin-cdn2\dist\chunk-WFIYNUVD.js:104:11)
at enter (D:\My Projects\MBDownload\frontend\node_modules\.pnpm\v[email protected]\node_modules\vite-plugin-cdn2\dist\chunk-WFIYNUVD.js:223:22)
at NodePath._call (D:\My Projects\MBDownload\frontend\node_modules\.pnpm\@[email protected]\node_modules\@babel\traverse\lib\path\context.js:46:20)
at NodePath.call (D:\My Projects\MBDownload\frontend\node_modules\.pnpm\@[email protected]\node_modules\@babel\traverse\lib\path\context.js:36:17)
at NodePath.visit (D:\My Projects\MBDownload\frontend\node_modules\.pnpm\@[email protected]\node_modules\@babel\traverse\lib\path\context.js:82:31)
at TraversalContext.visitQueue (D:\My Projects\MBDownload\frontend\node_modules\.pnpm\@[email protected]\node_modules\@babel\traverse\lib\context.js:86:16)
at TraversalContext.visitMultiple (D:\My Projects\MBDownload\frontend\node_modules\.pnpm\@[email protected]\node_modules\@babel\traverse\lib\context.js:61:17)
at TraversalContext.visit (D:\My Projects\MBDownload\frontend\node_modules\.pnpm\@[email protected]\node_modules\@babel\traverse\lib\context.js:107:19)
at traverseNode (D:\My Projects\MBDownload\frontend\node_modules\.pnpm\@[email protected]\node_modules\@babel\traverse\lib\traverse-node.js:18:17)
at NodePath.visit (D:\My Projects\MBDownload\frontend\node_modules\.pnpm\@[email protected]\node_modules\@babel\traverse\lib\path\context.js:88:52)
at TraversalContext.visitQueue (D:\My Projects\MBDownload\frontend\node_modules\.pnpm\@[email protected]\node_modules\@babel\traverse\lib\context.js:86:16)
at TraversalContext.visitSingle (D:\My Projects\MBDownload\frontend\node_modules\.pnpm\@[email protected]\node_modules\@babel\traverse\lib\context.js:65:19)
at TraversalContext.visit (D:\My Projects\MBDownload\frontend\node_modules\.pnpm\@[email protected]\node_modules\@babel\traverse\lib\context.js:109:19)
at traverseNode (D:\My Projects\MBDownload\frontend\node_modules\.pnpm\@[email protected]\node_modules\@babel\traverse\lib\traverse-node.js:18:17)
at traverse (D:\My Projects\MBDownload\frontend\node_modules\.pnpm\@[email protected]\node_modules\@babel\traverse\lib\index.js:49:34)
at CodeGen.transform (D:\My Projects\MBDownload\frontend\node_modules\.pnpm\v[email protected]\node_modules\vite-plugin-cdn2\dist\chunk-WFIYNUVD.js:198:20)
ELIFECYCLE Command failed with exit code 1.
在获取x的时候 x = b || p || i; i在前面优先使用用户配置的relativeModule
let { name: s, relativeModule: i, aliases: a, ...n } = r;
try {
let o = W.resolve(s), c = k(o, "package.json"), u = await F.readFile(c, "utf8"), f = JSON.parse(u), {
version: d,
name: l,
unpkg: p,
jsdelivr: b
} = f, g = Object.create(null), x = b || p || i;
if (!x) throw new Error("try resolve file failed.");
}
首先感谢作者的无私奉献。
请教一下关于如何加载 highlight.js
modules: [
'vue',
'highlight.js',
...
错误日志:
vite-plugin-cdn2: highlight.js try resolve file failed.
配置: cdn({
modules: [
{ name: 'axios', relativeModule: './axios.min.js' },
{ name: 'element-ui', relativeModule: './element-ui.min.js', aliases: ['client'] },
],
resolve: {
name: 'resolve:cdnjs',
setup({ extra }) {
const baseURL = 'https://cdnjs.cloudflare.com/ajax/libs/';
const { version, name, relativeModule } = extra;
console.log(relativeModule);
const url = new URL(${name}/${version}/${relativeModule}
, baseURL);
console.log(url);
return {
url: url.href,
injectTo: 'head-prepend',
attrs: {},
};
},
},
}),
ERROR vite-plugin-cdn2: axios Maximum call stack size exceeded
ERROR vite-plugin-cdn2: element-ui Maximum call stack size exceeded
我在vue2的版本上使用然后报错了 是我的配置不对吗
cdn({
modules: [{ name: "vue", relativeModule: "vue.global.prod.min.js" }, "vue-router", "vue-demi", "pinia", "axios" ],
resolve: defineResolve({
name: "resolve:custom",
setup({ extra }) {
const baseURL = "https://cdn.staticfile.net/";
const { version, name, relativeModule } = extra;
const url = new URL(`${name}/${version}/${relativeModule}`, baseURL);
return {
url: url.href,
injectTo: "head-prepend",
attrs: {
crossOrigin: 'anonymous'
},
};
},
})
})
And there is no vue
in output:
<script crossOrigin="anonymous" src="https://cdn.staticfile.net/vue-router/4.2.0/dist/vue-router.global.js"></script>
<script crossOrigin="anonymous" src="https://cdn.staticfile.net/vue-demi/0.14.6/lib/index.iife.js"></script>
<script crossOrigin="anonymous" src="https://cdn.staticfile.net/pinia/2.1.7/dist/pinia.iife.js"></script>
<script crossOrigin="anonymous" src="https://cdn.staticfile.net/axios/1.5.0/dist/axios.min.js"></script>
😭, it contains ljharb.
cdn 配置,resolve设置和没设置效果一样,还没进去resolve,貌似前一步还有一个scanner?扫描可用的包?之后才循环可用的包一一进入resolve。
我对插件方面不太熟悉,可能是我配置问题,麻烦大佬了,谢谢。
import { cdn } from 'vite-plugin-cdn2'
import { defineResolve } from 'vite-plugin-cdn2/resolve'
export const cdnConfig = cdn({
modules: [
{
name: 'dayjs',
global: 'dayjs',
relativeModule: 'dayjs.min.js'
},
{
name: 'echarts',
global: 'echarts',
// aliases: ['charts', 'code', 'components', 'types/dist/shared', 'features', 'renderers'],
relativeModule: 'dist/echarts.min.js'
}
],
resolve: defineResolve({
name: 'resolve:custom',
setup({ extra }) {
const baseURL = 'https://unpkg.com/browse/'
const { version, name, relativeModule } = extra
const url = new URL(`${name}@${version}/${relativeModule}`, baseURL)
return {
url: url.href,
injectTo: 'head-prepend',
attrs: {}
}
}
})
})
下面是日志,只输出了dayjs,echarts没有任何log,也建议输出一下为何不生效的原因,方便排查,谢谢
yarn.cmd run build-only
Active code page: 65001
yarn run v1.22.22
$ rimraf dist && set DEBUG=vite-plugin-cdn2 & vite build
vite-plugin-cdn2 start scanning +0ms
vite-plugin-cdn2 scanning done Map(1) {
'dayjs' => {
name: 'dayjs',
version: '1.11.12',
relativeModule: 'dayjs.min.js',
aliases: [],
global: 'dayjs',
bindings: Set(1) { 'default' }
}
} +472ms
vite v4.5.3 building for production...
🚀 开始构建
✓ 2202 modules transformed.
rendering chunks (2)... vite-plugin-cdn2 start transformIndexHtml +21s
vite-plugin-cdn2 transformIndexHtml Done [
{
tag: 'script',
injectTo: 'head-prepend',
attrs: { src: 'https://unpkg.com/browse/[email protected]/dayjs.min.js' }
}
] +0ms
dist/index.html 1.65 kB │ gzip: 0.88 kB
dist/assets/index-189109ff.css 1.54 kB │ gzip: 0.61 kB
dist/assets/index-803f298e.css 129.13 kB │ gzip: 18.47 kB
dist/assets/index-9f0f4ed5.js 96.92 kB │ gzip: 38.57 kB
dist/assets/index-8a686ba7.js 871.10 kB │ gzip: 299.55 kB
not support import * as Vue from vue;
demo
https://github.com/yulimchen/vue3-h5-template
package.json
"dependencies": {
"axios": "^1.6.2",
"normalize.css": "^8.0.1",
"nprogress": "^0.2.0",
"pinia": "^2.1.7",
"vant": "^4.7.3",
"vconsole": "^3.15.1",
"vue": "^3.3.4",
"vue-router": "^4.2.5"
},
"devDependencies": {
"vite-plugin-cdn2": "^1.1.0",
}
cdn.js
export function enableCDN(isEnabled) {
console.log("enableCDN", isEnabled);
if (isEnabled === "true" || isEnabled === true) {
console.log("enableCDN", isEnabled);
return cdn({
modules: [
{
name: "axios",
aliasName: "axios.min.js"
},
"normalize.css",
// {
// name: "normalize.css",
// spare: ["https://unpkg.com/[email protected]/normalize.css"]
// },
"nprogress",
{
name: "vue",
aliasName: "vue.global.js"
},
"vue-demi",
{
name: "vue-router",
aliasName: "vue-router.global.js"
},
{
name: "pinia",
aliasName: "pinia.iife.js"
},
{
name: "vant",
aliasName: "vant.min.js"
},
// {
// name: "vconsole",
// aliasName: "vconsole.min.js"
// }
"vconsole"
],
resolve: {
name: "resolve:custom",
setup({ extra }) {
const { name, aliasName, relativeModule, version } = extra;
let url = "";
if (name && aliasName) {
const baseURL = "https://cdn-anc.com";
url = new URL(`${aliasName}`, baseURL);
} else {
const baseURL = "https://unpkg.com/";
url = new URL(`${name}/${version}/${relativeModule}`, baseURL);
}
console.log("url", url);
return {
url: url.href,
injectTo: "head-prepend",
attrs: {}
};
}
}
});
}
}
ERROR vite-plugin-cdn2: normalize.css try resolve file failed. 10:59:12
ERROR vite-plugin-cdn2: nprogress try resolve file failed. 10:59:12
ERROR vite-plugin-cdn2: vconsole try resolve file failed.
配合vue-charts第三方插件,结合typescript按需引入,最终目标是cdn加载echarts,动态加载charts中的components及charts类型,参考代码。
项目配置:
cdn({
modules: [
'vue',
'vue-demi',
'pinia',
'vue-router',
{
name: 'element-plus',
aliases: ['lib', 'es'],
spare: [
'https://unpkg.com/[email protected]/dist/index.css',
'https://unpkg.com/[email protected]/theme-chalk/dark/css-vars.css'
]
},
{
name: 'echarts',
aliases: ['core', 'renderers', 'components', 'features', 'charts'] // 这一行是出问题的部分
}
]
})
ECharts的项目中的引用:
import { use } from 'echarts/core'
import { CanvasRenderer } from 'echarts/renderers'
import * as Charts from 'echarts/charts'
import * as ChartsComponents from 'echarts/components'
import * as ChartsFeatures from 'echarts/features'
import VChart from 'vue-echarts'
最小示例项目:
https://github.com/toimc/vite-vue-cdn-demo
错误问题:
尝试排查问题:
打开sourceMap,定位到是use方法出现问题,发现...Array.from(new Set(deps)).map((o) => ChartsComponents[o]),
这个部分是空,全是undefined
,开发模式是正常的,说明在线上的时候,
echarts/components应该是没有正常的被加载,所以对应的方法是空的,如何解决?
=======
PS:即使上面的代码出现了Bug,但是图表却正常的渲染了,奇怪了~
> set DEBUG=vite-plugin-cdn2 && vite build
vite-plugin-cdn2 start scanning +0ms
vite-plugin-cdn2 scanning done Map(0) {} +337ms
vite-plugin-cdn2: vue __require.resolve is not a function
vite v4.4.5 building for production...
mini demo: https://codesandbox.io/p/sandbox/vite-plugin-cdn2-not-work-s6p78h
我在vue2中使用出错了,因为这是旧项目 我不好使用vue3
配置 cdn({
modules: [
{ name: 'axios', relativeModule: './axios.min.js' },
{ name: 'element-ui', relativeModule: './element-ui.min.js', aliases: ['client'] },
],
resolve: {
name: 'resolve:cdnjs',
setup({ extra }) {
const baseURL = 'https://cdnjs.cloudflare.com/ajax/libs/';
const { version, name, relativeModule } = extra;
console.log(relativeModule);
const url = new URL(${name}/${version}/${relativeModule}
, baseURL);
console.log(url);
return {
url: url.href,
injectTo: 'head-prepend',
attrs: {},
};
},
},
}),
报错信息:
vite-plugin-cdn2: axios Maximum call stack size exceeded
vite-plugin-cdn2: element-ui Maximum call stack size exceeded
package.json:
"dependencies": {
"@tinymce/tinymce-vue": "2.0.0",
"axios": "0.18.1",
"element-china-area-data": "5.0.2",
"element-ui": "2.15.12",
"js-md5": "0.7.3",
"lodash": "4.17.21",
"normalize.css": "7.0.0",
"nprogress": "0.2.0",
"path-browserify": "1.0.1",
"path-to-regexp": "2.4.0",
"rollup-plugin-external-globals": "0.9.1",
"sortablejs": "1.13.0",
"tinymce": "^5.0.3",
"vue": "2.6.10",
"vue-cropper": "0.6.4",
"vue-dompurify-html": "2.6.0",
"vue-router": "3.0.6",
"vuedraggable": "2.24.3",
"vuex": "3.1.0",
"vuex-persistedstate": "^4.1.0"
},
"devDependencies": {
"rollup-plugin-visualizer": "5.12.0",
"sass": "1.26.8",
"unplugin-imagemin": "0.5.15",
"vite": "4.3.9",
"vite-plugin-cdn2": "1.1.0",
"vite-plugin-compression2": "0.11.0",
"vite-plugin-html": "3.2.0",
"vite-plugin-image-optimizer": "1.1.7",
"vite-plugin-theme": "0.8.6",
"vite-plugin-vue2": "2.0.3",
"vite-plugin-vue2-svg": "0.4.0",
"vue-template-compiler": "2.6.10"
},
Now many packages is only support esm cdn, the package should support what auto add importmap when scan external.
<script type="importmap">
{
"imports": {
"shiki": "https://cdn.jsdelivr.net/npm/shiki@~1.2.0/+esm"
}
}
</script>
modules 中排除 element-plus 后打包结果存在 [email protected][email protected]/node_modules/element-plus 如何解决?
由于cdn可能存在访问失败的问题。
希望增加备用方案。
通过属性配置是否开启 开启后不会排除使用了cdn的资源
并且 如果cdn超时未加载成功。还是使用项目资源进行加载
不知道方案是否可行
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.