Closed toimc closed 12 months ago
关于加入css的功能的话这个插件和vite-plugin-cdn-import
是不一样的。你只需要加入spare属性就行。spare:['css文件即可']
,关于vue-router
没按照cdn加载的话我得研究下在给你答复 @toimc
我目前查看了他的文档。检查你的本地项目是否包含vue-router/auto
和vue-router/auto/routes
如果包含 就设置对应的aliases.
具体配置如下
cdn({
modules: ['vue', {name:'ElementPlus',aliases:['es'],spare:['https://cdn.jsdelivr.net/npm/element-plus@2.4.2/dist/index.min.css'], {name:'vue-router',aliases:['auto','auto/routes']}}
})
非常感谢上面的回复。
[1]
我尝试了一下,vue-router/auto的问题解决了,但是spare属性未生效,生成的html中未发现css:
这个是新生成的html:
<!doctype html>
<html lang="en">
<head>
<script src="https://cdn.jsdelivr.net/npm/vue@3.3.8/dist/vue.global.js"></script>
<script src="https://cdn.jsdelivr.net/npm/element-plus@2.4.2/dist/index.full.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-demi@0.14.6/lib/index.iife.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue-router@4.2.5/dist/vue-router.global.js"></script>
<script src="https://cdn.jsdelivr.net/npm/pinia@2.1.7/dist/pinia.iife.js"></script>
<meta charset="UTF-8" />
<link rel="icon" href="/favicon.ico" />
<meta
name="viewport"
id="viewport"
content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, viewport-fit=cover"
/>
<title>Vite App</title>
<script type="module" crossorigin src="/assets/index-e808e22b.js"></script>
<link rel="stylesheet" href="/assets/index-f984f7b7.css">
<link rel="manifest" href="/manifest.webmanifest"></head>
<body class="m-safe">
<div id="app"></div>
</body>
</html>
配置如下:
modules: [
'vue',
{ name: 'element-plus', aliases: ['es', 'lib'] },
'vue-demi',
{
name: 'ElementPlus',
aliases: ['es'],
spare: ['https://cdn.jsdelivr.net/npm/element-plus@2.4.2/dist/index.min.css']
},
{ name: 'vue-router', aliases: ['auto', 'auto/routes'] },
'pinia'
],
logLevel: 'slient'
[2] 还有一个构建过程中的日志打印问题:
为什么开启了logLevl: 'slient' 还是会打印
这个log 应该是我无心之举。后面版本会进行修复
我应该是看错了。ElementPlus 这个应该没有用你自己配置的element-plus 是正确的。只需要把spare 移进去。
sorry,我发现问题了,我嵌套错位置了。
新配置如下:
modules: [
'vue',
{
name: 'element-plus',
aliases: ['es', 'lib'],
spare: ['https://cdn.jsdelivr.net/npm/element-plus@2.4.2/dist/index.min.css']
},
'vue-demi',
{ name: 'vue-router', aliases: ['auto', 'auto/routes'] },
'pinia'
],
[1]为什么项目中没有使用.prod的js,而是全部使用的是global.js,这一块如何设置?
[2]如果使用 unpkg.com
作为url,我觉得如下写resolve非常low,有没有优化建议?
resolve: (base, { name, version }) => {
// vue@3.3.8/dist/vue.global.js
switch (name) {
case 'vue':
case 'vue-router':
return `${base}/${name}@${version}/dist/${name}.global.prod.js`
case 'element-plus':
return `${base}/${name}@${version}/dist/index.full.min.js`
case 'vue-demi':
return `${base}/${name}@${version}/lib/index.iife.js`
default:
return `${base}/${name}@${version}/dist/${name}.iife.prod.js`
}
}
你可以使用relativeModule
。
[
{ name: 'vue', relativeModule: './dist/vue.global.prod.js' },
{
name: 'element-plus',
aliases: ['es', 'lib'],
relativeModule: './dist/index.full.min.js',
spare: ['https://cdn.jsdelivr.net/npm/element-plus@2.4.2/dist/index.min.css']
},
{ name: 'vue-demi', relativeModule: './dist/index.iife.js' },
{ name: 'vue-router', aliases: ['auto', 'auto/routes'], relativeModule: './dist/vue-router.global.prod.js' },
{ name: 'pinia', relativeModule: './dist/iife.prod.js' }
]
上面的解决方案非常棒,非常感谢。
有两个问题:
[1] 使用unplugin-vue-router 插件之后,如果使用 { name: 'vue-router', aliases: ['auto', 'auto/routes'], relativeModule: './dist/vue-router.global.prod.js' }
是可以把vue-router使用cdn加载的,但是项目打包会出问题,所以的项目组件都未成功生成:
这个是把vue-router排除在外的情况:
✓ 108 modules transformed.
dist/manifest.webmanifest 0.29 kB
dist/index.html 1.16 kB │ gzip: 0.52 kB
dist/assets/index-f984f7b7.css 20.77 kB │ gzip: 4.76 kB
dist/assets/404-2711b914.js 0.38 kB │ gzip: 0.27 kB
dist/assets/zh-cn-2b877b8e.js 1.61 kB │ gzip: 1.12 kB
dist/assets/zh-cn-476220b1.js 2.28 kB │ gzip: 0.90 kB
dist/assets/single-page-538c28e2.js 2.46 kB │ gzip: 1.14 kB
dist/assets/en-1fb5af88.js 2.48 kB │ gzip: 0.66 kB
dist/assets/en-3f1991e3.js 2.79 kB │ gzip: 1.22 kB
dist/assets/workbox-window.prod.es5-a7b12eab.js 5.29 kB │ gzip: 2.20 kB
dist/assets/index-1091f9ec.js 209.65 kB │ gzip: 70.56 kB
未排除在外的情况:
✓ 253 modules transformed.
dist/manifest.webmanifest 0.29 kB
dist/index.html 1.07 kB │ gzip: 0.51 kB
dist/assets/about-4d995ba2.css 0.09 kB │ gzip: 0.10 kB
dist/assets/draggable-85402e9d.css 0.12 kB │ gzip: 0.13 kB
dist/assets/ep-icon-picker-7eb084ee.css 0.12 kB │ gzip: 0.12 kB
dist/assets/CollapseTransition-e6724fa4.css 0.12 kB │ gzip: 0.11 kB
dist/assets/avatars-6ef93914.css 0.15 kB │ gzip: 0.12 kB
dist/assets/index-4e7f02f1.css 0.20 kB │ gzip: 0.12 kB
dist/assets/notice-message-bf637873.css 0.35 kB │ gzip: 0.23 kB
dist/assets/index-3dc731e4.css 26.58 kB │ gzip: 5.72 kB
dist/assets/route-block-83d24a4e.js 0.03 kB │ gzip: 0.05 kB
dist/assets/Popover-8e086f8e.js 0.10 kB │ gzip: 0.11 kB
dist/assets/menu2-8a94d0c8.js 0.18 kB │ gzip: 0.17 kB
dist/assets/menu1-2-7d501830.js 0.19 kB │ gzip: 0.17 kB
dist/assets/menu1-1-1-032dab54.js 0.19 kB │ gzip
... // 省略掉
dist/assets/index-610b58d1.js 241.45 kB │ gzip: 81.92 kB
优化index.js大概优化了40kb左右。
尝试下面的配置,解决:
{
name: 'vue-router',
aliases: ['auto'],
relativeModule: './dist/vue-router.global.prod.js'
},
[2] 删除vue-router,在开发模式下,项目能够正常启动,但是build&preview会出错:
Uncaught TypeError: Cannot read properties of undefined (reading 'BaseTransition')
at index-abc148f6.js:23:55328
(anonymous) @ index-abc148f6.js:23
看了一下,应该全是vue core的内容。
解决尝试1:
看了一下vue在head部分导入,没有问题,链接https://unpkg.com/vue@3.3.8/dist/vue.global.prod.js
正常访问
解决尝试2:
起初我怀疑是关闭了AutoImport与Components在production模式下的作用,resolvers: isProd ? [] : [ElementPlusResolver()]
,实际上,无效。
====== 目前卡在这里了,望回复。
具体使用了哪些插件呢。能提供一份配置表吗
当然可以,package.json
{
// ...
},
"dependencies": {
"@unocss/reset": "^0.57.4",
"@vueuse/core": "^10.6.1",
"dayjs": "^1.11.10",
"element-plus": "^2.4.2",
"gsap": "^3.12.2",
"pinia": "^2.1.7",
"pinia-plugin-persistedstate": "^3.2.0",
"sortablejs": "^1.15.0",
"vue": "^3.3.8",
"vue-i18n": "^9.6.5",
"vue-router": "^4.2.5"
},
"devDependencies": {
"@iconify/json": "^2.2.142",
"@iconify/vue": "^4.1.1",
"@intlify/unplugin-vue-i18n": "^1.5.0",
// ...
"@unocss/preset-wind": "^0.57.2",
"@vitejs/plugin-vue": "^4.4.1",
"@vitejs/plugin-vue-jsx": "^3.0.2",
"rollup-plugin-visualizer": "^5.9.2",
"sass": "^1.69.5",
"unocss": "^0.57.2",
"unplugin-auto-import": "^0.16.7",
"unplugin-vue-components": "^0.25.2",
"unplugin-vue-router": "^0.7.0",
"vite": "^4.5.0",
"vite-plugin-cdn2": "^0.15.1",
"vite-plugin-mock": "^3.0.0",
"vite-plugin-pwa": "^0.16.7",
"vite-plugin-svg-icons": "^2.0.1",
"vite-plugin-vue-layouts": "^0.8.0"
}
}
vite.config.ts:
// ..
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import { VueRouterAutoImports } from 'unplugin-vue-router'
import VueRouter from 'unplugin-vue-router/vite'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
// @ts-ignore
import Layouts from 'vite-plugin-vue-layouts'
import UnoCSS from 'unocss/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
import { VitePWA } from 'vite-plugin-pwa'
import { viteMockServe } from 'vite-plugin-mock'
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
import I18n from '@intlify/unplugin-vue-i18n/vite'
import { visualizer } from 'rollup-plugin-visualizer'
import { cdn } from 'vite-plugin-cdn2'
// https://vitejs.dev/config/
export default defineConfig(({ mode, command }) => {
const isProd = mode === 'production'
return {
plugins: [
VueRouter(),
vue({
script: {
defineModel: true,
propsDestructure: true
}
}),
vueJsx(),
UnoCSS(),
AutoImport({
include: [
/\.[tj]sx?$/, // .ts, .tsx, .js, .jsx
/\.vue$/,
/\.vue\?vue/, // .vue
/\.md$/ // .md
],
// global imports to register
imports: [
// presets
'vue',
// 'vue-router'
VueRouterAutoImports,
'@vueuse/core'
],
resolvers: isProd ? [] : [ElementPlusResolver()],
vueTemplate: true
}),
Components({
directoryAsNamespace: false,
collapseSamePrefixes: true,
resolvers: isProd ? [] : [ElementPlusResolver()]
}),
Layouts({
layoutsDirs: 'src/layouts',
defaultLayout: 'default'
}),
VitePWA({
manifest: {
name: 'Vite App',
short_name: 'Vite App',
theme_color: '#ffffff',
icons: [
{
src: '/192x192.png',
sizes: '192x192',
type: 'image/png'
},
{
src: '/512x512.png',
sizes: '512x512',
type: 'image/png'
}
]
},
registerType: 'autoUpdate'
}),
viteMockServe({
mockPath: 'mock',
enable: false
}),
createSvgIconsPlugin({
// 指定需要缓存的图标文件夹
iconDirs: [path.resolve(process.cwd(), 'src/assets/icons')],
// 指定symbolId格式
symbolId: 'icon-[dir]-[name]'
}),
I18n({
include: [path.resolve(__dirname, './locales/**')],
// 说明:由于配置了modules/i18n.ts中默认为legacy: false
// 所以禁止修改
compositionOnly: true,
jitCompilation: true
}),
visualizer({
open: true
}),
cdn({
url: 'https://unpkg.com',
modules: [
{ name: 'vue', relativeModule: './dist/vue.global.prod.js' },
{ name: 'vue-demi', relativeModule: './dist/index.iife.js' },
{
name: 'vue-router',
aliases: ['auto'],
relativeModule: './dist/vue-router.global.prod.js'
},
{
name: 'element-plus',
relativeModule: './dist/index.full.min.js',
aliases: ['es', 'lib'],
spare: [
'https://cdn.jsdelivr.net/npm/element-plus@2.4.2/dist/index.min.css',
'https://cdn.jsdelivr.net/npm/element-plus@2.4.2/theme-chalk/dark/css-vars.css'
]
},
{ name: 'pinia', relativeModule: './dist/iife.prod.js' }
],
logLevel: 'slient'
})
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
server: {
host: '0.0.0.0'
}
}
})
@toimc 我在本地制作了一个最小复现demo。我觉得你并不需要isProd 这个字段。autoImport
和components
的resolvers照常使用即可。不需要空数组。同时因为按需引入了。这里是题外话我觉得既然按需引入了那么ElementPlus
如果是轻度使用完全可以不用cdn.直接打包进去即可。因为这2个插件会附带引入css 打包进chunk这一点你可以注意一下。关于router的这个我没遇到问题。
我做了一个最小 demo,https://github.com/toimc/vite-vue-cdn-demo ,你可以在你本地试一下,pnpm dev正常,pnpm build-only && pnpm preview,无法运行。
关于:
我觉得你并不需要isProd 这个字段,autoImport 和components的resolvers照常使用即可——说明一下我这么做的原因:
理由一:由于项目中使用到component动态组件,有一些场景下,需要动态从服务端传递过来一些可能在当前resolver下没有打包进来了element-plus中的组件,所以要这么干;
理由二:由于"这2个插件会附带引入css 打包进chunk",正如你所说,我发现这2个插件会导致css会有100kb的增加,非常不nice,我直接考虑全部cdn加载,避免重复打包。
关于router的这个我没遇到问题——我上面已经回复,我目前的解决方案,可以参看最小 demo中的vite配置。
非常感谢!!!
关于router的这个问题。 我暂时没什么好思路。这个包不会特别大我会找个时间研究下这个插件具体的工作流。目前你可以先把他移除。以及tryScanGlobalName
去推测全局变量并不是万能的。我在用你的demo的时候发现了警告这时候你应该手动传入globalName。这个tryScanGlobalName
我也会进行优化尝试覆盖更多的mangle包
Pinia和VueDemi 配置错了应该是{ name: 'vue-demi', relativeModule: './lib/index.iife.js' },
和 { name: 'pinia', relativeModule: './dist/pinia.iife.prod.js' }
关于router的这个问题。 我暂时没什么好思路。这个包不会特别大我会找个时间研究下这个插件具体的工作流。目前你可以先把他移除。以及
tryScanGlobalName
去推测全局变量并不是万能的。我在用你的demo的时候发现了警告这时候你应该手动传入globalName。这个tryScanGlobalName
我也会进行优化尝试覆盖更多的mangle包
是的,我还发现,如果这样设置resolvers: isProd ? [] : [ElementPlusResolver()],
,打包之后,即使在head部分有加载css,但是依旧,页面加载不成功样式。
network中无请求:
见代码:
看起来是插件的bug。我会进行一个修复。 应急措施的话就得看文档了。
你是指vite-plugin-cdn插件有问题,还是指AutoImport及Components这两个插件有问题?
冒昧问一下,有什么思路没有?卡在这里了,想压缩项目打包的体积。
尝试一:rollup插件方式External + html静态资源导入又与vite-plugin-pwa这个插件冲突,打包之后html中无js,css 尝试二:rollup插件方式external + vite-plugin-html静态资源导入,资源导入的位置有问题,样式部分需要另外的js逻辑,无法external vue-router(这个与此插件表现一致) 尝试三:使用vite-plugin-cdn-import,与AutoImport及Components这两个插件不兼容,同时打包的文件,会重复打包i18n的locales翻译 js文件,即使已经external掉。
unplugin-vue-router
这个插件。 他的实现目前在我看来有点黑盒。这么说吧目前社区里面的external插件多多少少都有些不足 但是由于vite社区热衷于编译魔法导致一些edge case无法被很好的覆盖。
因为目前这类的插件实现原理都是大同小异无非是看谁的external做的更好罢了。
我发布了0.15.2
对插入问题进行了一个修复
我发布了
0.15.2
对插入问题进行了一个修复
经过我的尝试,已经OK了,感谢开源作者无私的付出。
cdn({
url: 'https://unpkg.com',
modules: [
{ name: 'vue', relativeModule: './dist/vue.global.prod.js' },
{ name: 'vue-demi', relativeModule: './lib/index.iife.js' },
// {
// name: 'vue-router',
// aliases: ['auto'],
// relativeModule: './dist/vue-router.global.prod.js'
// }, // 这一块未解决,参考 https://github.com/nonzzz/vite-plugin-cdn/issues/30
{
name: 'element-plus',
relativeModule: './dist/index.full.min.js',
aliases: ['es', 'lib'],
spare: [
'https://unpkg.com/element-plus@2.4.2/dist/index.css',
'https://unpkg.com/element-plus@2.4.2/theme-chalk/dark/css-vars.css'
]
},
{ name: 'pinia', relativeModule: './dist/pinia.iife.prod.js' },
{ name: 'vue-i18n', relativeModule: './dist/vue-i18n.global.prod.js' },
{ name: 'sortablejs', global: 'Sortablejs', relativeModule: './Sortable.min.js' }
]
})
最终配置,提供给有缘人。
感谢作者的无私付出,有两个小疑问。
[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打包进项目。
@nonzzz