nonzzz / vite-plugin-cdn

replace module with CDN. work with vite.
MIT License
75 stars 6 forks source link

能自定义 URL 吗? #11

Closed Bisstocuz closed 1 year ago

Bisstocuz commented 1 year ago

就像:

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 里安装的版本。

nonzzz commented 1 year ago

url的话会进行合并。你可以通过transform hook 去操作他。你提供的伪代码更像是一个tpl解析流。

nonzzz commented 1 year ago

具体使用的话目前只能


import { cdn } from 'vite-plugin-cdn2'

cdn({
  modules: ['vue'],
  transform() {
    return {
      script: (node) => {
        if (node.name === 'vue') {
          node.url.clear()
          node.url.add('https://cdn.bootcdn.net/ajax/libs/vue/3.0.2/vue.esm-browser.prod.js')
        }
      }
    }
  }
})

我感觉可以单独给node挂载一个详细的信息记录一些其他的内容

nonzzz commented 1 year ago

0.7.0版本发布了可以通过hook 访问到node的extra信息。里面包含了version之类的信息。

nonzzz commented 1 year ago

解析tpl的方式我暂时没有想到一个好的思路去平衡现有的逻辑。比如他和url option 冲突这件事

Bisstocuz commented 1 year ago

解析tpl的方式我暂时没有想到一个好的思路去平衡现有的逻辑。比如他和url option 冲突这件事

并不需要真的像解析模板一样实现啦,最简单的字符串 replace('{{ verion }}', <版本号>) 就能满足需求了,主要是不想每次更新了依赖还要来手动改插件配置。

    return {
      script: (node) => {
        if (node.name === 'vue') {
          node.url.clear()
          node.url.add('https://cdn.bootcdn.net/ajax/libs/vue/3.0.2/vue.esm-browser.prod.js')
        }
      }
    }

这里可以自定义替换 URL 的话,替换 {{ verion }} 的逻辑我可以自己实现,谢谢。

nonzzz commented 1 year ago

是可以替换的。

nonzzz commented 1 year ago

我本意一开始想的是开放最终bind到html上的hook 用来调整当前节点的信息。比如是否需要async 是否需要defer以及他的url是怎么样的

Bisstocuz commented 1 year ago

我本意一开始想的是开放最终bind到html上的hook 用来调整当前节点的信息。比如是否需要async 是否需要defer以及他的url是怎么样的

Vite 里面的 HtmlTagDescriptor 或许也可以暴露给用户修改的,像 Vite 的 Config 钩子一样,将返回值(HTML 标签属性)合并。

nonzzz commented 1 year ago

目前有个url option. 那么比如我传入的是vite那么你自己携带了url的话 是会生成1个script节点包含了一个url set。如果按照你说的如果给modules的item新增url参数。怎么取舍已有的spare是一件让我头疼的事情。


Map(2) {
  '__fake__script__' => {
    tag: 'script',
    url: Set(2) {
      'https://cdn.jsdelivr.net/npm/fake@0.0.0./fake.js',
      'fake2.js'
    },
    name: 'fake',
    extra: {
      relativeModule: 'fake.js',
      version: '0.0.0.',
      name: 'fake',
      spare: [Array]
    }
  },

类似于这样目前的node结构

nonzzz commented 1 year ago

比如


const modules  = [{name:'vue',url:'https://cdn.bootcdn.net/ajax/libs/vue/{{ version }}/vue.esm-browser.prod.js'}]

如果我们新增了这个参数我感觉目前的设计只能忽略掉插件的内部检索可能存在的逻辑。其实也不是不行。但是这个tpl解析我更希望是一个有效模板比如[url][name][version] 这样的方式?

Bisstocuz commented 1 year ago

[url][name][version]

其实 vite-plugin-cdn-import 有个参数 prodUrl 是这样的 https://cdn.jsdelivr.net/npm/{name}@{version}/{path},我觉得还蛮方便的。

nonzzz commented 1 year ago

我不会完全遵循vite-plugin-cdn-import 因为他分离了css和js的 url让我觉得很不可思议。关于url这个事情我感觉是可以给module item里面添加一个url参数。这个url可以是一个function 也可以是一个模板 你觉得呢?

Bisstocuz commented 1 year ago

我不会完全遵循vite-plugin-cdn-import 因为他分离了css和js的 url让我觉得很不可思议。关于url这个事情我感觉是可以给module item里面添加一个url参数。这个url可以是一个function 也可以是一个模板 你觉得呢?

可以的。

或者也可以参考 vite-plugin-jspm,让用户自己去实现一个 Provider 接口:https://jspm.org/docs/generator/stable/interfaces/GeneratorOptions.html#customProviders

nonzzz commented 1 year ago

我更希望插件的本身是stupid的。不需要考虑太多。是一种开箱即用的就行

Bisstocuz commented 1 year ago

我更希望插件的本身是stupid的。不需要考虑太多。是一种开箱即用的就行

😉 stupid 固然好,但是全都是 jsdelivr 这种对国内用户不算特别友好,还是希望部分组件能使用国内 CDN 提供商的,比如 Vue、Element Plus 这种大块头。

nonzzz commented 1 year ago

根据我的想法来看 doc 我更希望的是用户能轻量化配置。module item url的option我会实现并且发布新的版本。(因为存在着行为不一致)

nonzzz commented 1 year ago

不过我很好奇这个插件现在真有人用吗。。。

Bisstocuz commented 1 year ago

不过我很好奇这个插件现在真有人用吗。。。

仓库 24 stars,NPM 上的 Weekly Downloads 有 40+,少说也得有几百个用户了。🤣

nonzzz commented 1 year ago

这个插件本来是因为没法解决export * from 'module' 才实现的

nonzzz commented 1 year ago

我实现了[baseURL][version][name] 这样的模板他会和spare 同时工作 参照以下代码

cdn({
  url: 'https://cdn.bootcdn.net/ajax/libs',
  modules: [{ name: 'vue', url: '[baseURL]/[name]/[version]/vue.esm-browser.prod.js' }]
})

@Bisstocuz 你感觉如何呢? 我感觉url应该改成customProviders 好点url的定义不够明确

Bisstocuz commented 1 year ago

我实现了[baseURL][version][name] 这样的模板他会和spare 同时工作 参照以下代码

cdn({
  url: 'https://cdn.bootcdn.net/ajax/libs',
  modules: [{ name: 'vue', url: '[baseURL]/[name]/[version]/vue.esm-browser.prod.js' }]
})

@Bisstocuz 你感觉如何呢? 我感觉url应该改成customProviders 好点url的定义不够明确

这样可以的,customProviders 确实更好一些。

nonzzz commented 1 year ago

@Bisstocuz 新版本0.8.0 已经发布。 实现了resolve 可以进行快速的替换

nonzzz commented 1 year ago

更新了0.9.0 我发现可以有更快捷的方式参照example的设置这个版本优化了类型导出


import path from 'path'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import { VarletUIResolver } from 'unplugin-vue-components/resolvers'
import Components from 'unplugin-vue-components/vite'
import { cdn } from 'vite-plugin-cdn2'
import { unpkg } from 'vite-plugin-cdn2/url'
import { compression } from 'vite-plugin-compression2'
import Inspect from 'vite-plugin-inspect'

export default defineConfig(({ command }) => {
  return {
    plugins: [
      vue(),
      Components({ resolvers: [VarletUIResolver()] }),
      {
        ...cdn({
          url: 'https://cdn.bootcdn.net/ajax/libs/',
          modules: ['vue', 'vue-demi', 'pinia', '@varlet/ui', 'axios'],
          resolve(baseURL, { name, version, relativeModule }) {
            if (name === '@varlet/ui') return new URL(`${name}@${version}/${relativeModule}`, unpkg).href
            return new URL(`${name}/${version}/${path.basename(relativeModule)}`, baseURL).href
          }
        }),
        apply: command
      },
      compression({
        algorithm: 'gzip',
        threshold: 3 * 1024
      }),
      Inspect()
    ]
  }
})
nonzzz commented 1 year ago

所有的module会先走一次 resolve 然后 modules里面的resolve在执行。 最后再通过transform这个hook进行最终的操作。保证了版本一致性