11import path from 'node:path'
22import fs from 'fs-extra'
3- import fg from 'fast-glob'
4- import { dedupeCopyFiles } from './locateCdnNpmInfo.js'
53import { installPackageTemporary } from '../vite-plugins/installPackageTemporary.js'
6- import { babelReplaceImportPathWithCertainFileName } from './replaceImportPath.mjs'
4+ import { createEnvReplacementPlugin } from '../vite-plugins/createEnvReplacementPlugin.js'
5+ import { copyPlugin } from '../vite-plugins/cdnCopyPlugin.js'
6+ import { dedupeCopyFiles } from './locateCdnNpmInfo.js'
77
88const logger = console
99
10+ // 默认的复制配置,这几个 package 需要复制整个目录,所以需要有默认配置进行复制整个目录
1011const defaultCopyConfig = {
1112 '@opentiny/vue-theme' : {
1213 filePathInPackage : '/'
@@ -22,20 +23,6 @@ const defaultCopyConfig = {
2223 }
2324}
2425
25- /**
26- * 对文件内容进行转换处理
27- * @param {string } content - 文件内容
28- * @param {string } filename - 文件名
29- * @returns {string } - 处理后的内容
30- */
31- function replaceJsImportPaths ( content , filename ) {
32- if ( filename . endsWith ( '.js' ) ) {
33- const result = babelReplaceImportPathWithCertainFileName ( content , filename , console )
34- return result . code || content
35- }
36- return content
37- }
38-
3926/**
4027 * 从importMapUrl字符串中提取包名、版本和文件路径
4128 * @param {string } str - 导入字符串
@@ -60,172 +47,6 @@ function extractInfo(str) {
6047 }
6148}
6249
63- /**
64- * 创建环境变量替换插件
65- * @param {string } cdnDir - 本地CDN目录名
66- * @returns {Object } - Vite插件对象
67- */
68- function createEnvReplacementPlugin ( cdnDir , base ) {
69- return {
70- name : 'vite-replace-cdn-env' ,
71- config ( config ) {
72- // 在构建时替换环境变量,将CDN域名替换为本地路径
73- if ( ! config . define ) {
74- config . define = { }
75- }
76-
77- config . define [ 'import.meta.env.VITE_CDN_DOMAIN' ] = JSON . stringify (
78- `${ base . endsWith ( '/' ) ? base : base + '/' } ${ cdnDir } `
79- )
80- // 使用本地 CDN 时,强制设置CDN类型为 local
81- config . define [ 'import.meta.env.VITE_CDN_TYPE' ] = JSON . stringify ( 'local' )
82- }
83- }
84- }
85-
86- /**
87- * 复制文件或目录到目标路径
88- * @param {string } srcPath - 源文件/目录路径
89- * @param {string[] } destPaths - 目标路径数组
90- * @param {Set } copiedFiles - 已复制文件集合
91- * @param {string } outDir - 输出目录
92- */
93- async function copyFileOrDirectory ( srcPath , destPaths , copiedFiles , outDir ) {
94- // 生成一个唯一标识,避免重复复制相同文件
95- const copyId = `${ srcPath } :${ destPaths . join ( ',' ) } `
96-
97- if ( copiedFiles . has ( copyId ) ) {
98- logger . log ( `[vite-cdn-copy-plugin]: Skipping already copied file: ${ srcPath } ` )
99- return
100- }
101-
102- copiedFiles . add ( copyId )
103-
104- // 检查源文件是否存在
105- if ( ! fs . existsSync ( srcPath ) ) {
106- logger . warn ( `[vite-cdn-copy-plugin]: Source does not exist: ${ srcPath } ` )
107- return
108- }
109-
110- const isDirectory = fs . statSync ( srcPath ) . isDirectory ( )
111-
112- // 为每个目标路径执行复制
113- for ( const destPath of destPaths ) {
114- const fullDestPath = path . resolve ( outDir , destPath )
115-
116- try {
117- // 确保目标目录存在
118- await fs . ensureDir ( path . dirname ( fullDestPath ) )
119-
120- logger . log ( `[vite-cdn-copy-plugin]: Copying from ${ srcPath } to ${ fullDestPath } ` )
121-
122- if ( isDirectory ) {
123- // 如果是目录,使用 fast-glob 遍历所有文件并处理
124- logger . log ( `[vite-cdn-copy-plugin]: Copying directory recursively: ${ srcPath } -> ${ fullDestPath } ` )
125-
126- // 确保目标路径存在
127- await fs . ensureDir ( fullDestPath )
128-
129- // 使用绝对路径
130- const absoluteSrcPath = path . resolve ( process . cwd ( ) , srcPath )
131-
132- // 使用 fast-glob 查找所有文件
133- const files = fg . sync ( `${ absoluteSrcPath } /**/*` , { onlyFiles : true } )
134-
135- // 处理每个文件
136- for ( const file of files ) {
137- const relativePath = path . relative ( absoluteSrcPath , file )
138- const destFilePath = path . join ( fullDestPath , relativePath )
139-
140- // 确保目标文件的目录存在
141- await fs . ensureDir ( path . dirname ( destFilePath ) )
142-
143- // 读取文件内容
144- const content = await fs . readFile ( file , 'utf-8' )
145-
146- // 应用转换
147- const transformedContent = replaceJsImportPaths ( content , file )
148-
149- // 写入转换后的内容
150- await fs . writeFile ( destFilePath , transformedContent )
151- }
152- } else {
153- // 如果是单个文件
154- logger . log ( `[vite-cdn-copy-plugin]: Copying file: ${ srcPath } -> ${ fullDestPath } ` )
155-
156- let finalDestPath = path . join ( fullDestPath , path . basename ( srcPath ) )
157-
158- // 确保目标文件的目录存在
159- await fs . ensureDir ( path . dirname ( finalDestPath ) )
160-
161- // 读取文件内容
162- const content = await fs . readFile ( srcPath , 'utf-8' )
163-
164- // 应用转换
165- const transformedContent = replaceJsImportPaths ( content , srcPath )
166-
167- // 写入转换后的内容
168- await fs . writeFile ( finalDestPath , transformedContent )
169- }
170-
171- logger . log ( `[vite-cdn-copy-plugin]: Successfully copied: ${ srcPath } -> ${ fullDestPath } ` )
172- } catch ( err ) {
173- logger . error ( `[vite-cdn-copy-plugin]: Failed to copy ${ srcPath } to ${ fullDestPath } ` , err )
174- }
175- }
176- }
177-
178- /**
179- * 创建复制插件
180- * @param {Array<Object> } targets - 复制目标配置数组
181- * @param {string|Array<string> } targets[].src - 源文件路径或路径数组
182- * @param {string|Array<string> } targets[].dest - 目标文件路径或路径数组
183- * @returns {Object } Vite插件对象
184- */
185-
186- function copyPlugin ( targets ) {
187- let resolvedConfig = null
188- let copiedFiles = new Set ( )
189-
190- return {
191- name : 'vite-cdn-copy-plugin' ,
192- configResolved ( getResolvedConfig ) {
193- resolvedConfig = getResolvedConfig
194- } ,
195- async writeBundle ( ) {
196- if ( ! targets || ! targets . length ) {
197- return
198- }
199-
200- const outDir = resolvedConfig . build . outDir || 'dist'
201-
202- logger . log ( '[vite-cdn-copy-plugin]: Start copying files to dist directory' )
203-
204- // 遍历所有复制目标
205- for ( const target of targets ) {
206- const { src, dest } = target
207-
208- if ( ! src || ! dest ) {
209- logger . warn ( '[vite-cdn-copy-plugin]: Skipping target with missing src or dest' , target )
210- continue
211- }
212-
213- // 处理源路径,支持数组形式
214- // const srcPaths = (Array.isArray(src) ? src : [src]).map(item => path.resolve(process.cwd(), item))
215- const srcPaths = Array . isArray ( src ) ? src : [ src ]
216- // 处理目标路径,支持数组形式
217- const destPaths = Array . isArray ( dest ) ? dest : [ dest ]
218-
219- for ( const srcPath of srcPaths ) {
220- await copyFileOrDirectory ( srcPath , destPaths , copiedFiles , outDir )
221- }
222- }
223-
224- logger . log ( '[vite-cdn-copy-plugin]: Finished copying files' )
225- }
226- }
227- }
228-
22950/**
23051 * 比较两个版本号是否相同
23152 * @param {string } versionOrigin - 源版本号, 可能包含 ^ 或 ~ 开头
0 commit comments