build: 公共依赖cdn解耦并增加开关控制 (#360)
* build: external public cdn localize 公共cdn依赖包支持本地化 * build: cdn外部依赖解耦,修复baseUrl获取 * build: cdn依赖解耦 修正baseUrl获取方式 * build: cdn依赖三方解耦,优化目录型拷贝 * build: cdn依赖解耦,解决目录复制文件的相对路径问题 * build(design-core): 修复monaco的worker使用cdn地址前缀的情况下打包失效 * build: 本地开发也支持脱离cdn三方依赖 * build: 去除代码注释 * build: 三方cdn依赖解耦 物料bundle文件依赖支持替换cdn依赖 * build(design-core) 去除冗余用不到的文件和配置项硬编码 * build: 公共依赖cdn解耦测试完成 开关默认关闭 * refactor: 简化三方cdn依赖解耦的正则,改为path方法 * refactor: 三方依赖解耦脚本代码优化,减少雷同的正则匹配 * refactor: 三方cdn依赖解耦脚本 简化合并正则 * build: 三方cdn解耦 物料本地打包逻辑优化修正 * build: 三方cdn依赖解耦,优化代码简化正则,修复计算版本号问题,修复函数名大小写问题 * build: 优化importMap版本站位符号 * build: 三方cdn物料解耦 变量改为环境变量 * build: 三方cdn依赖解耦 补充处理复制文件夹时候的去重 * fix: 三方cdn解耦, 解决本地启动问题 * feat(preview): preview也支持cdn依赖解耦 * refactor(desing-core/scripts): 重构复制cdn文件本地复制模块 * build: 重构预览的importMap复制逻辑,修复两个importMap文件不存在 * build: 进一步优化monacoEditor地址,直接打包不再跨网络获取 * refactor(design-core/scripts): 调整复制应用importMap函数的参数顺序,与其他结构类似 * refactor(design-core/script): 调整文件位置和文件引用顺序 * feat(design-core/preview): preview importMap.js 使用 importMap.json 数据归一 * fix(design-core/preview): 修复importJson的引用 * fix: mock端口号订正,解决element-plus拖入画布后无法渲染 * build(design-core/script): 修复临时安装包插件安装完包后返回目录不正确 * fix: 修正monaco-editor的worker资源的打包地址 * build(design-core/script): 修复临时安装包插件安装完包后返回目录不正确 * fix(design-core/preview): 修正cdn解耦preview获取动态的importMap.json的base路径问题 * build: 三方cdn解耦,优化拷贝脚本,修复文件夹当文件拷贝当文件夹是包路径时候目标路径版本号丢失 * build: 三方cdn解耦,解决包未安装的情况下,glob匹配不到文件导致打包不拷贝内容 * fix: 根据检视意见使用fs-extra readJsonSync替代utils工具函数 * fix: 根据检视意见修改函数名大小写和端口号读取 * feat: 三方物料解耦 preview变量替换增加注释 * feat: 根据检视意见修改函数名字 * refactor: 根据检视意见,将脚本函数的参数整改为对象,并把目录值迁移到参数默认值 * docs(design-core/scripts): 三方cdn解耦 修正描述错误 * fix: 三方cdn解耦 修正preview脚本TinyVue版本号
This commit is contained in:
parent
3a66996fae
commit
899d616f7e
|
@ -5,6 +5,7 @@ package-lock.json
|
|||
yarn.lock
|
||||
pnpm-lock.yaml
|
||||
lerna-debug.log
|
||||
packages/design-core/bundle-deps
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
/**
|
||||
* Copyright (c) 2023 - present TinyEngine Authors.
|
||||
* Copyright (c) 2023 - present Huawei Cloud Computing Technologies Co., Ltd.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license.
|
||||
*
|
||||
* THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
|
||||
* BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
|
||||
*
|
||||
*/
|
||||
* Copyright (c) 2023 - present TinyEngine Authors.
|
||||
* Copyright (c) 2023 - present Huawei Cloud Computing Technologies Co., Ltd.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license.
|
||||
*
|
||||
* THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
|
||||
* BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
|
||||
* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
|
||||
*
|
||||
*/
|
||||
|
||||
export const NODE_UID = 'data-uid'
|
||||
export const NODE_TAG = 'data-tag'
|
||||
|
@ -125,9 +125,10 @@ export const getClipboardSchema = (event) => translateStringToSchame(event.clipb
|
|||
*/
|
||||
export const dynamicImportComponents = async ({ package: pkg, script, components }) => {
|
||||
if (!script) return
|
||||
const scriptUrl = script.startsWith('.') ? new URL(script, location.href).href : script
|
||||
|
||||
if (!window.TinyComponentLibs[pkg]) {
|
||||
const modules = await import(/* @vite-ignore */ script)
|
||||
const modules = await import(/* @vite-ignore */ scriptUrl)
|
||||
|
||||
window.TinyComponentLibs[pkg] = modules
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
NODE_ENV=production
|
||||
VITE_CDN_DOMAIN=https://npm.onmicrosoft.cn
|
||||
VITE_LOCAL_IMPORT_MAPS=false
|
||||
VITE_LOCAL_BUNDLE_DEPS=false
|
||||
# VITE_ORIGIN=
|
||||
|
||||
# 错误监控上报 url
|
||||
|
|
|
@ -2,5 +2,7 @@
|
|||
|
||||
NODE_ENV=development
|
||||
VITE_CDN_DOMAIN=https://npm.onmicrosoft.cn
|
||||
VITE_LOCAL_IMPORT_MAPS=false
|
||||
VITE_LOCAL_BUNDLE_DEPS=false
|
||||
# request data via alpha service
|
||||
# VITE_ORIGIN=
|
||||
# VITE_ORIGIN=
|
||||
|
|
|
@ -2,4 +2,6 @@
|
|||
|
||||
NODE_ENV=production
|
||||
VITE_CDN_DOMAIN=https://npm.onmicrosoft.cn
|
||||
#VITE_ORIGIN=
|
||||
VITE_LOCAL_IMPORT_MAPS=false
|
||||
VITE_LOCAL_BUNDLE_DEPS=false
|
||||
#VITE_ORIGIN=
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
<meta charset="UTF-8" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link href="%VITE_CDN_DOMAIN%/@opentiny/vue-theme@3.14/index.css" rel="stylesheet" />
|
||||
<style type="text/css">
|
||||
.loading-warp {
|
||||
display: flex;
|
||||
|
|
|
@ -120,9 +120,11 @@
|
|||
"rollup-plugin-polyfill-node": "^0.12.0",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"rollup-plugin-visualizer": "^5.8.3",
|
||||
"shelljs": "^0.8.5",
|
||||
"svg-sprite-loader": "^6.0.11",
|
||||
"vite": "^4.3.7",
|
||||
"vite-plugin-monaco-editor": "^1.0.10",
|
||||
"vite-plugin-monaco-editor": "^1.1.0",
|
||||
"vite-plugin-static-copy": "^0.16.0",
|
||||
"vite-plugin-svg-icons": "^2.0.1",
|
||||
"vue-eslint-parser": "^8.0.1"
|
||||
},
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
import path from 'node:path'
|
||||
import { readJsonSync } from 'fs-extra'
|
||||
import { installPackageTemporary } from '../vite-plugins/installPackageTemporary'
|
||||
import { configServerAddProxy } from '../vite-plugins/configureServerAddProxy'
|
||||
import { viteStaticCopy } from 'vite-plugin-static-copy'
|
||||
import {
|
||||
getCdnPathNpmInfoForSingleFile,
|
||||
getPackageNeedToInstallAndFilesUsingSameVersion,
|
||||
dedupeCopyFiles,
|
||||
copyfileToDynamicSrcMapper
|
||||
} from './locateCdnNpmInfo'
|
||||
|
||||
export function extraBundleCdnLink(filename, originCdnPrefix) {
|
||||
const result = []
|
||||
const bundle = readJsonSync(filename)
|
||||
bundle.data?.materials?.components?.forEach((component) => {
|
||||
if (component.npm) {
|
||||
const possibleUrl = [component.npm.script, component.npm.css]
|
||||
possibleUrl.forEach((url) => {
|
||||
if (url?.startsWith(originCdnPrefix) && !result.includes(url)) {
|
||||
result.push(url)
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
export function replaceBundleCdnLink(bundle, fileMap) {
|
||||
bundle.data?.materials?.components?.forEach((component) => {
|
||||
if (component.npm) {
|
||||
const possibleUrl = ['script', 'css']
|
||||
possibleUrl.forEach((key) => {
|
||||
const matchRule = fileMap.find((rule) => component.npm[key] === rule.originUrl)
|
||||
if (matchRule) {
|
||||
component.npm[key] = matchRule.newUrl
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function copyBundleDeps({
|
||||
bundleFile,
|
||||
targetBundleFile,
|
||||
originCdnPrefix,
|
||||
base,
|
||||
dir = 'material-static',
|
||||
bundleTempDir = 'bundle-deps/material-static'
|
||||
}) {
|
||||
const cdnFiles = extraBundleCdnLink(bundleFile, originCdnPrefix).map((url) =>
|
||||
getCdnPathNpmInfoForSingleFile(url, originCdnPrefix, base, dir, false, bundleTempDir)
|
||||
)
|
||||
const { packages: packageNeedToInstall, files } = getPackageNeedToInstallAndFilesUsingSameVersion(cdnFiles)
|
||||
|
||||
const plugin = (isDev) => {
|
||||
return [
|
||||
...(isDev ? configServerAddProxy(targetBundleFile, targetBundleFile.replace(/\.([^.]+?$)/, '-local.$1')) : []),
|
||||
...installPackageTemporary(packageNeedToInstall, bundleTempDir),
|
||||
...viteStaticCopy({
|
||||
targets: [
|
||||
...dedupeCopyFiles(files).map(copyfileToDynamicSrcMapper),
|
||||
{
|
||||
src: bundleFile,
|
||||
dest: path.dirname(targetBundleFile),
|
||||
transform: (content) => {
|
||||
const json = JSON.parse(content)
|
||||
replaceBundleCdnLink(json, files)
|
||||
return JSON.stringify(json, null, 2)
|
||||
},
|
||||
rename: (filename, fileExtension) =>
|
||||
isDev ? `${filename}-local.${fileExtension}` : path.basename(targetBundleFile),
|
||||
overwrite: true // 覆盖public的
|
||||
}
|
||||
]
|
||||
})
|
||||
]
|
||||
}
|
||||
return {
|
||||
plugin
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
import { viteStaticCopy } from 'vite-plugin-static-copy'
|
||||
import {
|
||||
getPackageNeedToInstallAndFilesUsingSameVersion,
|
||||
copyfileToDynamicSrcMapper,
|
||||
dedupeCopyFiles,
|
||||
getCdnPathNpmInfoForPackage,
|
||||
getCdnPathNpmInfoForSingleFile
|
||||
} from './locateCdnNpmInfo'
|
||||
import { importmapPlugin } from '../externalDeps'
|
||||
import { installPackageTemporary } from '../vite-plugins/installPackageTemporary'
|
||||
|
||||
export const copyLocalImportMap = ({
|
||||
importMap,
|
||||
styleUrls,
|
||||
originCdnPrefix,
|
||||
base,
|
||||
dir = 'import-map-static',
|
||||
bundleTempDir = 'bundle-deps/design-core-import-map',
|
||||
packageCopy = [] // 值为importMap的imports的左值 (非右值的地址上的包名)
|
||||
}) => {
|
||||
const importMapFiles = Object.entries(importMap.imports)
|
||||
.filter(([_libKey, libPath]) => libPath.startsWith(originCdnPrefix))
|
||||
.map(([libKey, libPath]) => {
|
||||
if (packageCopy.includes(libKey)) {
|
||||
return getCdnPathNpmInfoForPackage(libPath, originCdnPrefix, base, dir, true, bundleTempDir)
|
||||
}
|
||||
return getCdnPathNpmInfoForSingleFile(libPath, originCdnPrefix, base, dir, false, bundleTempDir)
|
||||
})
|
||||
const styleFiles = styleUrls
|
||||
.filter((styleUrl) => styleUrl.startsWith(originCdnPrefix))
|
||||
.map((url) => getCdnPathNpmInfoForSingleFile(url, originCdnPrefix, base, dir, false), bundleTempDir)
|
||||
|
||||
const { packages: packageNeedToInstall, files } = getPackageNeedToInstallAndFilesUsingSameVersion(
|
||||
importMapFiles.concat(styleFiles)
|
||||
)
|
||||
|
||||
return [
|
||||
...installPackageTemporary(packageNeedToInstall, bundleTempDir),
|
||||
...viteStaticCopy({
|
||||
targets: dedupeCopyFiles(files).map(copyfileToDynamicSrcMapper)
|
||||
}),
|
||||
{
|
||||
config(config, { command }) {
|
||||
// 处理devAlias带CDN域名, 另外需要使得本地vue和importMap的vue是同一个实例
|
||||
if (command === 'serve') {
|
||||
config.resolve.alias = [
|
||||
...config.resolve.alias,
|
||||
{
|
||||
find: /^vue$/,
|
||||
replacement: `http://localhost:${config.server.port || 8080}/${
|
||||
files.find(({ originUrl }) => importMap.imports.vue === originUrl).newUrl
|
||||
}` // 实际端口号需要更具本地启动修改
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
importmapPlugin(
|
||||
{
|
||||
imports: Object.fromEntries(
|
||||
Object.entries(importMap.imports).map(([k, v]) => [k, files.find((f) => f.originUrl === v)?.newUrl ?? v])
|
||||
)
|
||||
},
|
||||
styleUrls.map((url) => styleFiles.find((f) => f.originUrl === url).newUrl ?? url)
|
||||
)
|
||||
]
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
import path from 'node:path'
|
||||
import { readJsonSync } from 'fs-extra'
|
||||
import {
|
||||
getPackageNeedToInstallAndFilesUsingSameVersion,
|
||||
copyfileToDynamicSrcMapper,
|
||||
dedupeCopyFiles,
|
||||
getCdnPathNpmInfoForPackage,
|
||||
getCdnPathNpmInfoForSingleFile
|
||||
} from './locateCdnNpmInfo'
|
||||
import { viteStaticCopy } from 'vite-plugin-static-copy'
|
||||
import { installPackageTemporary } from '../vite-plugins/installPackageTemporary'
|
||||
|
||||
export function extraPreviewImport(filename, originCdnPrefix) {
|
||||
const result = []
|
||||
const importMap = readJsonSync(filename)
|
||||
Object.entries(importMap.imports)?.forEach(([_key, location]) => {
|
||||
const url = location.replace('${VITE_CDN_DOMAIN}', originCdnPrefix).replace('${opentinyVueVersion}', '~3.14')
|
||||
if (url?.startsWith(originCdnPrefix) && !result.includes(url)) {
|
||||
result.push(url)
|
||||
}
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
export function replacePreviewImport(importMap, fileMap, originCdnPrefix) {
|
||||
return {
|
||||
imports: Object.fromEntries(
|
||||
Object.entries(importMap.imports)?.map(([key, location]) => {
|
||||
// 这里的替换占位符规则等同于packages/design-core/src/preview/src/preview/importMap.js, 两边修改需要同步
|
||||
const url = location.replace('${VITE_CDN_DOMAIN}', originCdnPrefix).replace('${opentinyVueVersion}', '~3.14')
|
||||
const matchRule = fileMap.find((rule) => url === rule.originUrl)
|
||||
if (matchRule) {
|
||||
return [key, matchRule.newUrl]
|
||||
}
|
||||
return [key, location]
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export function extraPreviewImportFile(filename, targetFileName, originCdnPrefix) {
|
||||
return (fileMap) => [
|
||||
{
|
||||
src: filename,
|
||||
dest: path.dirname(targetFileName),
|
||||
transform: (content) => {
|
||||
return JSON.stringify(replacePreviewImport(JSON.parse(content), fileMap, originCdnPrefix), null, 2)
|
||||
},
|
||||
rename: path.basename(targetFileName)
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
export function copyPreviewImportMap({
|
||||
importMapJson,
|
||||
targetImportMapJson,
|
||||
originCdnPrefix,
|
||||
base,
|
||||
dir = 'preview-import-map-static',
|
||||
bundleTempDir = 'bundle-deps/preview-import-map',
|
||||
packageCopyLib = [] // 值为cdn地址上的包名
|
||||
}) {
|
||||
const cdnFiles = extraPreviewImport(importMapJson, originCdnPrefix).map((url) => {
|
||||
const { packageName } = url.match(
|
||||
new RegExp(`^${originCdnPrefix}/?(?<packageName>.+?)@(?<versionDemand>[^/]+)(?<filePathInPackage>.*?)$`)
|
||||
).groups
|
||||
if (packageCopyLib.includes(packageName)) {
|
||||
return getCdnPathNpmInfoForPackage(url, originCdnPrefix, base, dir, true, bundleTempDir)
|
||||
}
|
||||
return getCdnPathNpmInfoForSingleFile(url, originCdnPrefix, base, dir, false, bundleTempDir)
|
||||
})
|
||||
const { packages: packageNeedToInstall, files } = getPackageNeedToInstallAndFilesUsingSameVersion(cdnFiles)
|
||||
return [
|
||||
...installPackageTemporary(packageNeedToInstall, bundleTempDir),
|
||||
...viteStaticCopy({
|
||||
targets: [
|
||||
...dedupeCopyFiles(files).map(copyfileToDynamicSrcMapper),
|
||||
...extraPreviewImportFile(importMapJson, targetImportMapJson, originCdnPrefix)(files)
|
||||
]
|
||||
})
|
||||
]
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
export * from './copyBundleDeps'
|
||||
export * from './copyImportMap'
|
||||
export * from './copyPreviewImportMap'
|
||||
export * from './utils'
|
||||
export * from './locateCdnNpmInfo'
|
||||
export * from './replaceImportPath.mjs'
|
|
@ -0,0 +1,204 @@
|
|||
import path from 'node:path'
|
||||
import fs from 'node:fs'
|
||||
import fg from 'fast-glob'
|
||||
import { normalizePath } from 'vite'
|
||||
import { readJsonSync } from 'fs-extra'
|
||||
import { babelReplaceImportPathWithCertainFileName } from './replaceImportPath.mjs'
|
||||
|
||||
function transform(content, filename) {
|
||||
if (filename.endsWith('.js')) {
|
||||
const result = babelReplaceImportPathWithCertainFileName(content, filename, console)
|
||||
return result.code || content
|
||||
}
|
||||
return content
|
||||
}
|
||||
|
||||
function onlyFiles(globString) {
|
||||
// viteStaticCopy 自带的glob匹配无法过滤目录, 手动过滤目录作为数组传入
|
||||
return fg.sync(globString + '/**/*', { onlyFiles: true }).map((p) => normalizePath(p))
|
||||
}
|
||||
|
||||
function replaceTailSlash(pathStr) {
|
||||
// 替换尾部的 / 可以把目录当文件复制
|
||||
return pathStr.replace(/\/$/, '')
|
||||
}
|
||||
|
||||
export function copyfileToDynamicSrcMapper({ src, dest, transform, rename, folder, ...rest }) {
|
||||
// viteStaticCopy 自带的glob匹配无法过滤目录, 手动过滤目录作为数组传入,但是不存在的包需要推迟glob的时机到安装文件后
|
||||
return {
|
||||
...rest,
|
||||
get src() {
|
||||
// 注意对象不能被解构,否则getter无法动态计算
|
||||
return src || onlyFiles(folder)
|
||||
},
|
||||
dest,
|
||||
transform,
|
||||
rename
|
||||
}
|
||||
}
|
||||
|
||||
// 生成复制单个文件所需要的信息
|
||||
export function getCdnPathNpmInfoForSingleFile(
|
||||
url, // cdn托管的npm文件地址数组
|
||||
originCdnPrefix, // cdn的前缀
|
||||
base, // build构建的base(BASE_URL)参数
|
||||
dir, // 复制到目标的文件目录
|
||||
transformIContent = false, // 是否需要转换内容, 如果传入url实际为目录则不会转会
|
||||
tempDir = 'bundle-deps' // 新安装包的安装目录
|
||||
) {
|
||||
const baseSlash = base.endsWith('/') ? '' : '/'
|
||||
const { packageName, versionDemand, filePathInPackage } = url.match(
|
||||
new RegExp(`^${originCdnPrefix}/?(?<packageName>.+?)@(?<versionDemand>[^/]+)(?<filePathInPackage>.*?)$`)
|
||||
).groups
|
||||
let version = versionDemand
|
||||
let isFolder = filePathInPackage.endsWith('/')
|
||||
let src = replaceTailSlash(`node_modules/${packageName}${filePathInPackage}`)
|
||||
const sourceExist = fs.existsSync(path.resolve(src))
|
||||
let sourceExistExternal = false
|
||||
if (sourceExist) {
|
||||
const stat = fs.statSync(path.resolve(src))
|
||||
if (stat.isDirectory()) {
|
||||
isFolder = true
|
||||
}
|
||||
const content = readJsonSync(`node_modules/${packageName}/package.json`)
|
||||
version = content.version // 忽略请求的包版本,使用本地包版本号
|
||||
} else {
|
||||
src = tempDir + '/' + src
|
||||
sourceExistExternal = fs.existsSync(path.resolve(src)) // 安装过的不重新安装, 当且仅当所有包都安装过
|
||||
if (sourceExistExternal) {
|
||||
const packageJson = readJsonSync(`${tempDir}/node_modules/${packageName}/package.json`)
|
||||
version = packageJson.version // 如果重新安装这个版本号还需要刷新
|
||||
}
|
||||
}
|
||||
const updateVersion = (version) => {
|
||||
const destPackageDir = `${dir}/${packageName}@${version}`
|
||||
const destFullPath = `${destPackageDir}${filePathInPackage}`
|
||||
const destFullPathWithoutTailSlash = replaceTailSlash(destFullPath)
|
||||
const dest = path.dirname(destFullPathWithoutTailSlash)
|
||||
const rename = dest.startsWith(destPackageDir) ? null : path.basename(destFullPathWithoutTailSlash) // 版本号被截断,需要补充回去
|
||||
return {
|
||||
version,
|
||||
newUrl: `${base}${baseSlash}${destFullPath}`,
|
||||
dest,
|
||||
rename
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
originUrl: url,
|
||||
// newUrl, // overwrite by updateVersion(version)
|
||||
src,
|
||||
// dest, // overwrite by updateVersion(version)
|
||||
packageName,
|
||||
// version, // overwrite by updateVersion(version)
|
||||
versionDemand,
|
||||
filePathInPackage,
|
||||
sourceExist,
|
||||
sourceExistExternal,
|
||||
...updateVersion(version),
|
||||
updateVersion,
|
||||
transform: transformIContent && !isFolder ? transform : null
|
||||
}
|
||||
}
|
||||
|
||||
export function getCdnPathNpmInfoForPackage(
|
||||
url, // cdn托管的npm文件地址数组
|
||||
originCdnPrefix, // cdn的前缀
|
||||
base, // build构建的base(BASE_URL)参数
|
||||
dir, // 复制到目标的文件目录
|
||||
transformIContent = false, // 是否需要转换内容
|
||||
tempDir = 'bundle-deps' // 新安装包的安装目录
|
||||
) {
|
||||
const baseSlash = base.endsWith('/') ? '' : '/'
|
||||
const { packageName, versionDemand, filePathInPackage } = url.match(
|
||||
new RegExp(`^${originCdnPrefix}/?(?<packageName>.+?)@(?<versionDemand>[^/]+)(?<filePathInPackage>.*?)$`)
|
||||
).groups
|
||||
let version = versionDemand
|
||||
let src = `node_modules/${packageName}`
|
||||
const sourceExist = fs.existsSync(path.resolve(src))
|
||||
let sourceExistExternal = false
|
||||
if (sourceExist) {
|
||||
const content = readJsonSync(`${src}/package.json`)
|
||||
version = content.version // 忽略请求的包版本,使用本地包版本号
|
||||
} else {
|
||||
src = tempDir + '/' + src
|
||||
sourceExistExternal = fs.existsSync(path.resolve(src)) // 安装过的不重新安装, 当且仅当所有包都安装过
|
||||
if (sourceExistExternal) {
|
||||
const packageJson = readJsonSync(`${src}/package.json`)
|
||||
version = packageJson.version // 如果重新安装这个版本号还需要刷新
|
||||
}
|
||||
}
|
||||
const updateVersion = (version) => {
|
||||
const packageDir = `${dir}/${packageName}@${version}`
|
||||
const packageDirBasename = path.basename(packageDir)
|
||||
return {
|
||||
version,
|
||||
newUrl: `${base}${baseSlash}${dir}/${packageName}@${version}${filePathInPackage}`,
|
||||
dest: path.dirname(packageDir),
|
||||
rename: (_filename, _fileExtension, fullPath) => `${packageDirBasename}${fullPath.replace(src, '')}`
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
folder: src,
|
||||
originUrl: url,
|
||||
// newUrl, // overwrite by updateVersion(version)
|
||||
src: sourceExist || sourceExistExternal ? onlyFiles(src) : null,
|
||||
// dest, // overwrite by updateVersion(version)
|
||||
packageName,
|
||||
// version, // overwrite by updateVersion(version)
|
||||
versionDemand,
|
||||
filePathInPackage,
|
||||
sourceExist,
|
||||
sourceExistExternal,
|
||||
...updateVersion(version),
|
||||
updateVersion,
|
||||
transform: transformIContent ? transform : null
|
||||
}
|
||||
}
|
||||
|
||||
export function dedupeCopyFiles(files) {
|
||||
return files.reduce((acc, cur) => {
|
||||
//去重,分别处理字符串和数组
|
||||
if (
|
||||
(cur.folder && !acc.some((item) => !!item.folder && item.folder === cur.folder && item.dest === cur.dest)) || // 文件夹拷贝
|
||||
(typeof cur.src === 'string' && !acc.some((item) => item.src === cur.src && item.dest === cur.dest)) // 文件拷贝
|
||||
) {
|
||||
acc.push(cur)
|
||||
}
|
||||
return acc
|
||||
}, [])
|
||||
}
|
||||
|
||||
export function getPackageNeedToInstallAndFilesUsingSameVersion(files) {
|
||||
const packageNeedToInstall = files
|
||||
.filter((item) => !item.sourceExist)
|
||||
.map(({ packageName, version, sourceExistExternal: exist }) => ({ packageName, version, exist }))
|
||||
.reduce((acc, cur) => {
|
||||
// 同个包避免多个版本只保留一个版本
|
||||
if (!acc.some(({ packageName }) => cur.packageName === packageName)) {
|
||||
acc.push(cur)
|
||||
}
|
||||
return acc
|
||||
}, [])
|
||||
let newFiles = null
|
||||
if (packageNeedToInstall.length) {
|
||||
// 确保同个包多个版本只能从一个版本引用文件
|
||||
newFiles = files.map((file) => {
|
||||
const samePackageDifferentVersion = packageNeedToInstall.find(
|
||||
({ packageName, version }) => packageName === file.packageName && version !== file.version
|
||||
)
|
||||
if (samePackageDifferentVersion) {
|
||||
return {
|
||||
...file,
|
||||
...file.updateVersion(samePackageDifferentVersion.version)
|
||||
}
|
||||
}
|
||||
return file
|
||||
})
|
||||
}
|
||||
return {
|
||||
packages: packageNeedToInstall,
|
||||
files: newFiles ?? files
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import { parse } from '@babel/core'
|
||||
import traversePkg from '@babel/traverse'
|
||||
import generatePkg from '@babel/generator'
|
||||
const traverse = traversePkg.default
|
||||
const generate = generatePkg.default
|
||||
|
||||
export function relativePathPattern(relativePath) {
|
||||
return './' + (path.sep === '/' ? relativePath : relativePath.replace(/\\/g, '/'))
|
||||
}
|
||||
|
||||
export function resolvePath(importPath, currentFilePath) {
|
||||
if (['js', 'mjs'].some(suffix =>importPath.endsWith(suffix))) { // 文件名已经带有.js,.mjs后缀
|
||||
return importPath
|
||||
}
|
||||
const parentPath = path.resolve(currentFilePath, '../')
|
||||
const filePrefix = path.resolve(parentPath, importPath)
|
||||
|
||||
if (fs.existsSync(filePrefix)) {
|
||||
const stat = fs.statSync(filePrefix)
|
||||
if (stat.isDirectory()) {
|
||||
let mainFileName = 'index.js'
|
||||
|
||||
const packageFile = path.resolve(filePrefix, 'package.json')
|
||||
|
||||
if (fs.existsSync(packageFile)) {
|
||||
const packageFileContent = fs.readFileSync(packageFile, { encoding: 'utf-8' })
|
||||
const packageJson = JSON.parse(packageFileContent)
|
||||
mainFileName = packageJson.module || packageJson.main || mainFileName
|
||||
}
|
||||
|
||||
const mainFile = path.resolve(filePrefix, mainFileName)
|
||||
if (fs.existsSync(mainFile)) {
|
||||
return relativePathPattern(path.relative(parentPath, mainFile))
|
||||
}
|
||||
return null
|
||||
}
|
||||
return importPath
|
||||
}
|
||||
const possibleSuffix = ['.js', '.mjs']
|
||||
const suffix = possibleSuffix.find(suf => fs.existsSync(filePrefix + suf))
|
||||
if (suffix) {
|
||||
return relativePathPattern(path.relative(path.resolve(currentFilePath, '../'), filePrefix + suffix))
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
// babel 替换 js的相对地址引用为确定文件后缀
|
||||
export function babelReplaceImportPathWithCertainFileName(content, currentFilePath, logger = console) {
|
||||
let fileChangedMark = false
|
||||
let result = {
|
||||
code: null,
|
||||
success: [],
|
||||
error: []
|
||||
}
|
||||
const ast = parse(content, { sourceType: 'module' })
|
||||
traverse(ast, {
|
||||
ImportOrExportDeclaration: (astPath) => {
|
||||
const node = astPath.node
|
||||
if (!node.source) {
|
||||
return
|
||||
}
|
||||
const importPath = node.source.value
|
||||
if(importPath.startsWith('.')) {
|
||||
const certainPath = resolvePath(importPath, currentFilePath)
|
||||
if(!certainPath) {
|
||||
logger.warn(`File not found: ${importPath} used in ${currentFilePath}`)
|
||||
result.error.push(importPath)
|
||||
}
|
||||
if(certainPath !== importPath) {
|
||||
node.source.value = certainPath
|
||||
fileChangedMark = true
|
||||
result.success.push({before: importPath, after: certainPath})
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
if (fileChangedMark) {
|
||||
const { code } = generate(ast, {
|
||||
jsescOption: {
|
||||
quotes: 'single'
|
||||
}
|
||||
})
|
||||
result.code = code
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
export function getBaseUrlFromCli(fallback = '') {
|
||||
// 理论上要从resolvedConfig阶段的钩子里面拿到base,由于插件嵌套插件,子插件的配置项需要在resolveConfig前传入这里,无法等resolvedConfig,故手动获取命令行base
|
||||
const index = process.argv?.indexOf('--base')
|
||||
return index > -1 ? process.argv[index + 1] || fallback : fallback
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
export function configServerAddProxy(path, target) {
|
||||
return [
|
||||
{
|
||||
name: 'vite-plugin-config-server-add-proxy',
|
||||
configureServer(server) {
|
||||
server.middlewares.use((req, _res, next) => {
|
||||
if (req.url.includes(path)) {
|
||||
req.url = req.url.replace(path, target)
|
||||
}
|
||||
next()
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
import fs from 'node:fs'
|
||||
import path from 'node:path'
|
||||
import shelljs from 'shelljs'
|
||||
|
||||
export function installPackageTemporary(packageNeedToInstall, tempDir, logger = console) {
|
||||
return [
|
||||
{
|
||||
name: 'vite-plugin-install-package-temporary',
|
||||
buildStart() {
|
||||
if (packageNeedToInstall.every((pkg) => pkg.exist)) {
|
||||
logger.info(`[vite-plugin-install-package-temporary]: bundle dependencies packages exist, skip install `)
|
||||
return
|
||||
}
|
||||
|
||||
let code = shelljs.mkdir('-p', tempDir).code
|
||||
if (code === 0) {
|
||||
//code 为 0 表示成功
|
||||
fs.writeFileSync(
|
||||
path.resolve(tempDir, 'package.json'),
|
||||
JSON.stringify(
|
||||
{
|
||||
name: 'bundle-deps', // tempDir to 烤串
|
||||
dependencies: Object.fromEntries(packageNeedToInstall.map((cur) => [cur.packageName, cur.version]))
|
||||
},
|
||||
null,
|
||||
2
|
||||
),
|
||||
{ encoding: 'utf-8' }
|
||||
)
|
||||
}
|
||||
code =
|
||||
code ||
|
||||
shelljs.cd(tempDir).code ||
|
||||
shelljs.exec(`npm install --force`).code ||
|
||||
shelljs.cd(path.relative(tempDir, '.')).code
|
||||
|
||||
if (code === 0) {
|
||||
logger.info(
|
||||
`[vite-plugin-install-package-temporary]: bundle dependencies package install success, total ${packageNeedToInstall.length} package(s)`
|
||||
)
|
||||
} else {
|
||||
logger.warn(`[vite-plugin-install-package-temporary]: bundle dependencies package install failed`)
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -22,7 +22,7 @@ import { genSFCWithDefaultPlugin, parseRequiredBlocks } from '@opentiny/tiny-eng
|
|||
import importMap from './importMap'
|
||||
import srcFiles from './srcFiles'
|
||||
import generateMetaFiles, { processAppJsCode } from './generate'
|
||||
import { getSearchParams, fetchMetaData, fetchAppSchema, fetchBlockSchema } from './http'
|
||||
import { getSearchParams, fetchMetaData, fetchImportMap, fetchAppSchema, fetchBlockSchema } from './http'
|
||||
import { PanelType, PreviewTips } from '../constant'
|
||||
import { injectDebugSwitch } from './debugSwitch'
|
||||
import '@vue/repl/style.css'
|
||||
|
@ -51,8 +51,6 @@ export default {
|
|||
}
|
||||
}
|
||||
|
||||
store.setImportMap(importMap)
|
||||
|
||||
// 相比store.setFiles,只要少了state.activeFile = state.files[filename],因为改变activeFile会触发多余的文件解析
|
||||
const setFiles = async (newFiles, mainFileName) => {
|
||||
await store.setFiles(newFiles, mainFileName)
|
||||
|
@ -61,7 +59,7 @@ export default {
|
|||
store['initTsConfig']() // 触发获取组件d.ts方便调试
|
||||
}
|
||||
|
||||
const addUtilsImportMap = (utils = []) => {
|
||||
const addUtilsImportMap = (importMap, utils = []) => {
|
||||
const utilsImportMaps = {}
|
||||
utils.forEach(({ type, content: { package: packageName, cdnLink } }) => {
|
||||
if (type === 'npm' && cdnLink) {
|
||||
|
@ -100,14 +98,27 @@ export default {
|
|||
}
|
||||
|
||||
const queryParams = getSearchParams()
|
||||
const getImportMap = async () => {
|
||||
if (import.meta.env.VITE_LOCAL_BUNDLE_DEPS === 'true') {
|
||||
const mapJSON = await fetchImportMap()
|
||||
return {
|
||||
imports: {
|
||||
...mapJSON.imports,
|
||||
...getSearchParams().scripts
|
||||
}
|
||||
}
|
||||
}
|
||||
return importMap
|
||||
}
|
||||
|
||||
const promiseList = [
|
||||
fetchAppSchema(queryParams?.app),
|
||||
fetchMetaData(queryParams),
|
||||
setFiles(srcFiles, 'src/Main.vue')
|
||||
setFiles(srcFiles, 'src/Main.vue'),
|
||||
getImportMap()
|
||||
]
|
||||
Promise.all(promiseList).then(async ([appData, metaData]) => {
|
||||
addUtilsImportMap(metaData.utils || [])
|
||||
Promise.all(promiseList).then(async ([appData, metaData, _void, importMapData]) => {
|
||||
addUtilsImportMap(importMapData, metaData.utils || [])
|
||||
|
||||
const blocks = await getBlocksSchema(queryParams.pageInfo?.schema)
|
||||
|
||||
|
|
|
@ -51,5 +51,10 @@ export const fetchMetaData = async ({ platform, app, type, id, history, tenant }
|
|||
})
|
||||
: {}
|
||||
|
||||
export const fetchImportMap = async () => {
|
||||
const baseUrl = new URL(import.meta.env.BASE_URL, location.href)
|
||||
return fetch(new URL('./preview-import-map-static/preview-importmap.json', baseUrl).href).then((res) => res.json())
|
||||
}
|
||||
|
||||
export const fetchAppSchema = async (id) => http.get(`/app-center/v1/api/apps/schema/${id}`)
|
||||
export const fetchBlockSchema = async (blockName) => http.get(`/material-center/api/block?label=${blockName}`)
|
||||
|
|
|
@ -13,37 +13,19 @@
|
|||
// import { hyphenate } from '@vue/shared'
|
||||
|
||||
import { getSearchParams } from './http'
|
||||
import importMapJSON from './importMap.json'
|
||||
import { VITE_CDN_DOMAIN } from '@opentiny/tiny-engine-controller/js/environments'
|
||||
|
||||
const importMap = {}
|
||||
|
||||
const opentinyVueVersion = '~3.14'
|
||||
|
||||
const tinyVue3Imports = {
|
||||
// 推荐之后统一使用@opentiny/vue去引入依赖,兼容后续录入的组件来源于tiny-vue
|
||||
'@opentiny/vue': `${VITE_CDN_DOMAIN}/@opentiny/vue@${opentinyVueVersion}/runtime/tiny-vue.mjs`,
|
||||
'@opentiny/vue-icon': `${VITE_CDN_DOMAIN}/@opentiny/vue@${opentinyVueVersion}/runtime/tiny-vue-icon.mjs`,
|
||||
'@opentiny/vue-common': `${VITE_CDN_DOMAIN}/@opentiny/vue@${opentinyVueVersion}/runtime/tiny-vue-common.mjs`,
|
||||
'@opentiny/vue-locale': `${VITE_CDN_DOMAIN}/@opentiny/vue@${opentinyVueVersion}/runtime/tiny-vue-locale.mjs`,
|
||||
'@opentiny/vue-renderless/': `${VITE_CDN_DOMAIN}/@opentiny/vue-renderless@${opentinyVueVersion}/`
|
||||
function replacePlaceholder(v) {
|
||||
return v.replace('${VITE_CDN_DOMAIN}', VITE_CDN_DOMAIN).replace('${opentinyVueVersion}', opentinyVueVersion)
|
||||
}
|
||||
|
||||
importMap.imports = {
|
||||
vue: `${VITE_CDN_DOMAIN}/vue@3.2.36/dist/vue.runtime.esm-browser.js`,
|
||||
'vue/server-renderer': `${VITE_CDN_DOMAIN}/@vue/server-renderer@3.2.36/dist/server-renderer.esm-browser.js`,
|
||||
'vue-i18n': `${VITE_CDN_DOMAIN}/vue-i18n@9.2.0-beta.36/dist/vue-i18n.esm-browser.js`,
|
||||
'vue-router': `${VITE_CDN_DOMAIN}/vue-router@4.0.16/dist/vue-router.esm-browser.js`,
|
||||
'@vue/devtools-api': `${VITE_CDN_DOMAIN}/@vue/devtools-api@6.5.1/lib/esm/index.js`,
|
||||
'@vueuse/core': `${VITE_CDN_DOMAIN}/@vueuse/core@9.6.0/index.mjs`,
|
||||
'@vueuse/shared': `${VITE_CDN_DOMAIN}/@vueuse/shared@9.6.0/index.mjs`,
|
||||
axios: `${VITE_CDN_DOMAIN}/axios@1.0.0-alpha.1/dist/esm/axios.js`,
|
||||
'axios-mock-adapter': `${VITE_CDN_DOMAIN}/axios-mock-adapter@1.21.1/dist/axios-mock-adapter.js`,
|
||||
'@opentiny/tiny-engine-webcomponent-core': `${VITE_CDN_DOMAIN}/@opentiny/tiny-engine-webcomponent-core@1/dist/tiny-engine-webcomponent-core.es.js`,
|
||||
'@opentiny/tiny-engine-i18n-host': `${VITE_CDN_DOMAIN}/@opentiny/tiny-engine-i18n-host@1/dist/tiny-engine-i18n-host.es.js`,
|
||||
'@opentiny/tiny-engine-builtin-component': `${VITE_CDN_DOMAIN}/@opentiny/tiny-engine-builtin-component@1/dist/index.js`,
|
||||
'vue-demi': `${VITE_CDN_DOMAIN}/vue-demi@0.13.11/lib/index.mjs`,
|
||||
pinia: `${VITE_CDN_DOMAIN}/pinia@2.0.22/dist/pinia.esm-browser.js`,
|
||||
...tinyVue3Imports,
|
||||
...Object.fromEntries(Object.entries(importMapJSON.imports).map(([k, v]) => [k, replacePlaceholder(v)])),
|
||||
...getSearchParams().scripts
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"imports": {
|
||||
"vue": "${VITE_CDN_DOMAIN}/vue@3.4.23/dist/vue.runtime.esm-browser.js",
|
||||
"vue/server-renderer": "${VITE_CDN_DOMAIN}/@vue/server-renderer@3.4.23/dist/server-renderer.esm-browser.js",
|
||||
"vue-i18n": "${VITE_CDN_DOMAIN}/vue-i18n@9.2.0-beta.36/dist/vue-i18n.esm-browser.js",
|
||||
"vue-router": "${VITE_CDN_DOMAIN}/vue-router@4.0.16/dist/vue-router.esm-browser.js",
|
||||
"@vue/devtools-api": "${VITE_CDN_DOMAIN}/@vue/devtools-api@6.5.1/lib/esm/index.js",
|
||||
"@vueuse/core": "${VITE_CDN_DOMAIN}/@vueuse/core@9.6.0/index.mjs",
|
||||
"@vueuse/shared": "${VITE_CDN_DOMAIN}/@vueuse/shared@9.6.0/index.mjs",
|
||||
"axios": "${VITE_CDN_DOMAIN}/axios@1.0.0/dist/esm/axios.js",
|
||||
"axios-mock-adapter": "${VITE_CDN_DOMAIN}/axios-mock-adapter@1.21.1/dist/axios-mock-adapter.js",
|
||||
"@opentiny/tiny-engine-webcomponent-core": "${VITE_CDN_DOMAIN}/@opentiny/tiny-engine-webcomponent-core@1/dist/tiny-engine-webcomponent-core.es.js",
|
||||
"@opentiny/tiny-engine-i18n-host": "${VITE_CDN_DOMAIN}/@opentiny/tiny-engine-i18n-host@1/dist/lowcode-design-i18n-host.es.js",
|
||||
"@opentiny/tiny-engine-builtin-component": "${VITE_CDN_DOMAIN}/@opentiny/tiny-engine-builtin-component@1/dist/index.js",
|
||||
"vue-demi": "${VITE_CDN_DOMAIN}/vue-demi@0.13.11/lib/index.mjs",
|
||||
"pinia": "${VITE_CDN_DOMAIN}/pinia@2.0.22/dist/pinia.esm-browser.js",
|
||||
"@opentiny/vue": "${VITE_CDN_DOMAIN}/@opentiny/vue@${opentinyVueVersion}/runtime/tiny-vue.mjs",
|
||||
"@opentiny/vue-icon": "${VITE_CDN_DOMAIN}/@opentiny/vue@${opentinyVueVersion}/runtime/tiny-vue-icon.mjs",
|
||||
"@opentiny/vue-common": "${VITE_CDN_DOMAIN}/@opentiny/vue@${opentinyVueVersion}/runtime/tiny-vue-common.mjs",
|
||||
"@opentiny/vue-locale": "${VITE_CDN_DOMAIN}/@opentiny/vue@${opentinyVueVersion}/runtime/tiny-vue-locale.mjs",
|
||||
"@opentiny/vue-renderless/": "${VITE_CDN_DOMAIN}/@opentiny/vue-renderless@${opentinyVueVersion}/"
|
||||
}
|
||||
}
|
|
@ -12,6 +12,7 @@ import lowcodeConfig from './config/lowcode.config'
|
|||
import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
|
||||
import { importmapPlugin } from './scripts/externalDeps'
|
||||
import visualizer from 'rollup-plugin-visualizer'
|
||||
import { getBaseUrlFromCli, copyBundleDeps, copyPreviewImportMap, copyLocalImportMap } from './scripts/localCdnFile'
|
||||
|
||||
const origin = 'http://localhost:9090/'
|
||||
|
||||
|
@ -197,14 +198,16 @@ const commonAlias = {
|
|||
}
|
||||
|
||||
export default defineConfig(({ command, mode }) => {
|
||||
const { VITE_CDN_DOMAIN } = loadEnv(mode, process.cwd(), '')
|
||||
const monacoPublicPath = {
|
||||
local: 'editor/monaco-workers',
|
||||
alpha: 'https://tinyengine-assets.obs.cn-north-4.myhuaweicloud.com/files/monaco-assets',
|
||||
prod: 'https://tinyengine-assets.obs.cn-north-4.myhuaweicloud.com/files/monaco-assets'
|
||||
}
|
||||
const { VITE_CDN_DOMAIN, VITE_LOCAL_IMPORT_MAPS, VITE_LOCAL_BUNDLE_DEPS } = loadEnv(mode, process.cwd(), '')
|
||||
const isLocalImportMap = VITE_LOCAL_IMPORT_MAPS === 'true' // true公共依赖库使用本地打包文件,false公共依赖库使用公共CDN
|
||||
const isCopyBundleDeps = VITE_LOCAL_BUNDLE_DEPS === 'true' // true bundle里的cdn依赖处理成本地依赖, false 不处理
|
||||
|
||||
let monacoEditorPluginInstance = monacoEditorPlugin({ publicPath: monacoPublicPath.local })
|
||||
const monacoPublicPath = 'editor/monaco-workers'
|
||||
const monacoEditorPluginInstance = monacoEditorPlugin({
|
||||
publicPath: monacoPublicPath,
|
||||
forceBuildCDN: true,
|
||||
customDistPath: (_root, outDir, _base) => path.join(outDir, monacoPublicPath)
|
||||
})
|
||||
const htmlPlugin = (mode) => {
|
||||
const upgradeHttpsMetaTags = []
|
||||
const includeHtmls = ['index.html', 'preview.html', 'previewApp.html']
|
||||
|
@ -241,7 +244,7 @@ export default defineConfig(({ command, mode }) => {
|
|||
}
|
||||
|
||||
config.resolve.alias = [
|
||||
devVueAlias,
|
||||
...(isLocalImportMap ? [] : [devVueAlias]),
|
||||
...Object.entries({ ...commonAlias, ...devAlias }).map(([find, replacement]) => ({
|
||||
find,
|
||||
replacement
|
||||
|
@ -251,8 +254,6 @@ export default defineConfig(({ command, mode }) => {
|
|||
// command === 'build'
|
||||
config.resolve.alias = { ...commonAlias, ...prodAlias }
|
||||
|
||||
monacoEditorPluginInstance = monacoEditorPlugin({ publicPath: monacoPublicPath[mode] })
|
||||
|
||||
if (mode === 'prod') {
|
||||
config.build.minify = true
|
||||
config.build.sourcemap = false
|
||||
|
@ -276,14 +277,49 @@ export default defineConfig(({ command, mode }) => {
|
|||
'@opentiny/vue-common': `${VITE_CDN_DOMAIN}/@opentiny/vue@${importMapVersions.tinyVue}/runtime/tiny-vue-common.mjs`,
|
||||
'@opentiny/vue-locale': `${VITE_CDN_DOMAIN}/@opentiny/vue@${importMapVersions.tinyVue}/runtime/tiny-vue-locale.mjs`,
|
||||
'@opentiny/vue-design-smb': `${VITE_CDN_DOMAIN}/@opentiny/vue-design-smb@${importMapVersions.tinyVue}/index.js`,
|
||||
'@opentiny/vue-theme/theme-tool': `${VITE_CDN_DOMAIN}/@opentiny/vue-theme@${importMapVersions.tinyVue}/theme-tool`,
|
||||
'@opentiny/vue-theme/theme': `${VITE_CDN_DOMAIN}/@opentiny/vue-theme@${importMapVersions.tinyVue}/theme`
|
||||
'@opentiny/vue-theme/theme-tool': `${VITE_CDN_DOMAIN}/@opentiny/vue-theme@${importMapVersions.tinyVue}/theme-tool.js`,
|
||||
'@opentiny/vue-theme/theme': `${VITE_CDN_DOMAIN}/@opentiny/vue-theme@${importMapVersions.tinyVue}/theme/index.js`
|
||||
}
|
||||
}
|
||||
|
||||
const importMapStyles = [`${VITE_CDN_DOMAIN}/@opentiny/vue-theme@${importMapVersions.tinyVue}/index.css`]
|
||||
|
||||
config.plugins.push(monacoEditorPluginInstance, htmlPlugin(mode), importmapPlugin(importmap, importMapStyles))
|
||||
|
||||
config.plugins.push(
|
||||
monacoEditorPluginInstance,
|
||||
htmlPlugin(mode),
|
||||
isLocalImportMap
|
||||
? copyLocalImportMap({
|
||||
importMap: importmap,
|
||||
styleUrls: importMapStyles,
|
||||
originCdnPrefix: VITE_CDN_DOMAIN,
|
||||
base: getBaseUrlFromCli(config.base),
|
||||
packageCopy: [
|
||||
// 这两个包的js存在相对路径引用,不能单独拷贝一个文件,需要整个包拷贝
|
||||
'@opentiny/vue-theme/theme-tool',
|
||||
'@opentiny/vue-theme/theme'
|
||||
]
|
||||
})
|
||||
: importmapPlugin(importmap, importMapStyles),
|
||||
isCopyBundleDeps
|
||||
? copyBundleDeps({
|
||||
bundleFile: 'public/mock/bundle.json',
|
||||
targetBundleFile: 'mock/bundle.json',
|
||||
originCdnPrefix: VITE_CDN_DOMAIN, // mock 中bundle的域名当前和环境的VITE_CDN_DOMAIN一致
|
||||
base: getBaseUrlFromCli(config.base)
|
||||
}).plugin(command === 'serve')
|
||||
: [],
|
||||
isLocalImportMap
|
||||
? copyPreviewImportMap({
|
||||
importMapJson: './src/preview/src/preview/importMap.json',
|
||||
targetImportMapJson: 'preview-import-map-static/preview-importmap.json',
|
||||
originCdnPrefix: VITE_CDN_DOMAIN,
|
||||
base: getBaseUrlFromCli(config.base),
|
||||
packageCopyLib: [
|
||||
// 以下的js存在相对路径引用,不能单独拷贝一个文件,需要整个包拷贝
|
||||
'@vue/devtools-api'
|
||||
]
|
||||
})
|
||||
: []
|
||||
)
|
||||
return config
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue