diff --git a/README.md b/README.md index 3d0d002..fa88141 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,6 @@ export default (): UserConfigExport => { }, }, { - importTest: /^El.*/, libraryName: 'element-plus', resolveStyle: (name) => { return `element-plus/lib/theme-chalk/${name}.css`; diff --git a/README.zh_CN.md b/README.zh_CN.md index ad672ff..8d39cf3 100644 --- a/README.zh_CN.md +++ b/README.zh_CN.md @@ -99,7 +99,6 @@ export default (): UserConfigExport => { }, }, { - importTest: /^El.*/, libraryName: 'element-plus', resolveStyle: (name) => { return `element-plus/lib/theme-chalk/${name}.css`; diff --git a/example/package.json b/example/package.json index 059a54e..c2a7838 100644 --- a/example/package.json +++ b/example/package.json @@ -12,6 +12,7 @@ "vue": "^3.0.11" }, "devDependencies": { + "@types/rollup": "^0.54.0", "@vitejs/plugin-vue": "^1.2.1", "@vitejs/plugin-vue-jsx": "^1.1.3", "@vue/compiler-sfc": "^3.0.11", diff --git a/example/vite.config.ts b/example/vite.config.ts index 2df37ed..bf00379 100644 --- a/example/vite.config.ts +++ b/example/vite.config.ts @@ -12,6 +12,7 @@ export default (): UserConfigExport => { }, }, }, + plugins: [ vue(), jsx(), @@ -33,8 +34,9 @@ export default (): UserConfigExport => { }, }, { - importTest: /^El.*/, libraryName: 'element-plus', + ensureStyleFile: true, + esModule: true, resolveStyle: (name) => { return `element-plus/lib/theme-chalk/${name}.css`; }, diff --git a/example/yarn.lock b/example/yarn.lock index 4837afe..714b9d8 100644 --- a/example/yarn.lock +++ b/example/yarn.lock @@ -335,6 +335,13 @@ resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.167.tgz#ce7d78553e3c886d4ea643c37ec7edc20f16765e" integrity sha512-w7tQPjARrvdeBkX/Rwg95S592JwxqOjmms3zWQ0XZgSyxSLdzWaYH3vErBhdVS/lRBX7F8aBYcYJYTr5TMGOzw== +"@types/rollup@^0.54.0": + version "0.54.0" + resolved "https://registry.npmjs.org/@types/rollup/-/rollup-0.54.0.tgz#e3ab3a7b3c1bf92969602dd92a589de39f324a31" + integrity sha512-oeYztLHhQ98jnr+u2cs1c3tHOGtpzrm9DJlIdEjznwoXWidUbrI+X6ib7zCkPIbB7eJ7VbbKNQ5n/bPnSg6Naw== + dependencies: + rollup "*" + "@vant/icons@^1.5.3": version "1.5.3" resolved "https://registry.npmjs.org/@vant/icons/-/icons-1.5.3.tgz#b7779f67bf608d417a82452fbede406dfa46b439" @@ -1229,6 +1236,13 @@ resolve@^1.19.0: is-core-module "^2.1.0" path-parse "^1.0.6" +rollup@*: + version "2.45.2" + resolved "https://registry.npmjs.org/rollup/-/rollup-2.45.2.tgz#8fb85917c9f35605720e92328f3ccbfba6f78b48" + integrity sha512-kRRU7wXzFHUzBIv0GfoFFIN3m9oteY4uAsKllIpQDId5cfnkWF2J130l+27dzDju0E6MScKiV0ZM5Bw8m4blYQ== + optionalDependencies: + fsevents "~2.3.1" + rollup@^2.38.5: version "2.39.0" resolved "https://registry.npmjs.org/rollup/-/rollup-2.39.0.tgz#be4f98c9e421793a8fec82c854fb567c35e22ab6" diff --git a/src/index.ts b/src/index.ts index fe31d87..ae99f73 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,5 @@ import type { Plugin } from 'vite'; +import type { ExternalOption } from 'rollup'; import type { ChangeCaseType, @@ -12,14 +13,19 @@ import * as changeCase from 'change-case'; import { init, parse, ImportSpecifier } from 'es-module-lexer'; import MagicString from 'magic-string'; import path from 'path'; -import { normalizePath } from 'vite'; import { debug as Debug } from 'debug'; -import fs from 'fs'; +import { + fileExists, + isRegExp, + // judgeResultFun, + resolveNodeModules, +} from './utils'; const debug = Debug('vite-plugin-style-import'); const ensureFileExts: string[] = ['.css', 'js', '.scss', '.less', '.styl']; +const asRE = /\s+as\s+\w+,?/g; const isFn = (value: any): value is (...args: any[]) => any => value != null && Object.prototype.toString.call(value) === '[object Function]'; @@ -35,6 +41,7 @@ export default (options: VitePluginComponentImport): Plugin => { let needSourcemap = false; let isBuild = false; + let external: ExternalOption | undefined; debug('plugin options:', options); @@ -44,6 +51,7 @@ export default (options: VitePluginComponentImport): Plugin => { configResolved(resolvedConfig) { needSourcemap = !!resolvedConfig.build.sourcemap; isBuild = resolvedConfig.isProduction || resolvedConfig.command === 'build'; + external = resolvedConfig?.build?.rollupOptions?.external ?? undefined; debug('plugin config:', resolvedConfig); }, async transform(code, id) { @@ -71,7 +79,7 @@ export default (options: VitePluginComponentImport): Plugin => { const { n, se, ss } = imports[index]; if (!n) continue; - const lib = getLib(n, libs); + const lib = getLib(n, libs, external); if (!lib) continue; const isResolveComponent = isBuild && !!lib.resolveComponent; @@ -104,6 +112,13 @@ export default (options: VitePluginComponentImport): Plugin => { if (isResolveComponent && compNameList.some((item) => importVariables.includes(item))) { str().remove(ss, endIndex); + // let importStr = str().slice(ss, endIndex); + // const { same, overwriteStr } = await removeAlreadyName(importStr, compNameList); + // if (same) { + // str().remove(ss, endIndex); + // } else { + // str().overwrite(ss, endIndex, overwriteStr); + // } } } return { @@ -118,10 +133,22 @@ function filterImportVariables(importVars: readonly string[], reg?: RegExp) { if (!reg) { return importVars; } - return importVars.filter((item) => reg.test(item)); } +// async function removeAlreadyName(importStr: string, compNameList: string[]) { +// const exportStr = importStr.replace('import', 'export').replace(asRE, ','); +// const same = judgeResultFun(parse(exportStr)[1], compNameList); +// let overwriteStr = importStr.replace(asRE, ','); +// if (!same) { +// compNameList.forEach((comp) => { +// overwriteStr = overwriteStr.replace(new RegExp(`${comp}\s*,?`), ''); +// }); +// } + +// return { same, overwriteStr }; +// } + // Generate the corresponding component css string array function transformComponentCss(root: string, lib: Lib, importVariables: readonly string[]) { const { @@ -139,6 +166,9 @@ function transformComponentCss(root: string, lib: Lib, importVariables: readonly const name = getChangeCaseFileName(importVariables[index], libraryNameChangeCase); let importStr = resolveStyle(name); + if (!importStr) { + continue; + } if (esModule) { importStr = resolveNodeModules(root, importStr); } @@ -198,7 +228,7 @@ export function transformImportVar(importStr: string) { return []; } - const exportStr = importStr.replace('import', 'export').replace(/\s+as\s+\w+,?/g, ','); + const exportStr = importStr.replace('import', 'export').replace(asRE, ','); let importVariables: readonly string[] = []; try { importVariables = parse(exportStr)[1]; @@ -232,17 +262,27 @@ function tryEnsureFile(root: string, filePath: string, esModule = false) { return filePathList.some((item) => fileExists(item)); } -function fileExists(f: string) { - try { - fs.accessSync(f, fs.constants.W_OK); - return true; - } catch (error) { - return false; +function getLib(libraryName: string, libs: Lib[], external?: ExternalOption) { + let libList = libs; + if (external) { + const isString = typeof external === 'string'; + const isRE = isRegExp(external); + if (isString) { + libList = libList.filter((item) => item.libraryName !== external); + } else if (isRE) { + libList = libList.filter((item) => !(external as RegExp).test(item.libraryName)); + } else if (Array.isArray(external)) { + libList = libList.filter((item) => { + return !external.some((val) => { + if (typeof val === 'string') { + return val === item.libraryName; + } + return (val as RegExp).test(item.libraryName); + }); + }); + } } -} - -function getLib(libraryName: string, libs: Lib[]) { - return libs.find((item) => item.libraryName === libraryName); + return libList.find((item) => item.libraryName === libraryName); } // File name conversion style @@ -263,7 +303,3 @@ function needTransform(code: string, libs: Lib[]) { return !new RegExp(`('${libraryName}')|("${libraryName}")`).test(code); }); } - -function resolveNodeModules(root: string, ...dir: string[]) { - return normalizePath(path.join(root, 'node_modules', ...dir)); -} diff --git a/src/utils.ts b/src/utils.ts new file mode 100644 index 0000000..4cd3f4d --- /dev/null +++ b/src/utils.ts @@ -0,0 +1,34 @@ +import path from 'path'; +import { normalizePath } from 'vite'; +import fs from 'fs'; + +export function resolveNodeModules(root: string, ...dir: string[]) { + return normalizePath(path.join(root, 'node_modules', ...dir)); +} + +export function isRegExp(value: unknown) { + return Object.prototype.toString.call(value) === '[object RegExp]'; +} + +// export function judgeResultFun(arr1: readonly string[], arr2: string[]) { +// let flag = true; +// if (arr1.length !== arr2.length) { +// flag = false; +// } else { +// arr1.forEach((item) => { +// if (arr2.indexOf(item) === -1) { +// flag = false; +// } +// }); +// } +// return flag; +// } + +export function fileExists(f: string) { + try { + fs.accessSync(f, fs.constants.W_OK); + return true; + } catch (error) { + return false; + } +} diff --git a/yarn.lock b/yarn.lock index 4db6c22..549a2ad 100644 --- a/yarn.lock +++ b/yarn.lock @@ -827,6 +827,11 @@ resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz#98a993516c859eb0d5c4c8f098317a9ea68db9ad" integrity sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA== +"@types/lodash@^4.14.168": + version "4.14.168" + resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.168.tgz#fe24632e79b7ade3f132891afff86caa5e5ce008" + integrity sha512-oVfRvqHV/V6D1yifJbVRU3TMp8OT6o6BG+U9MkwuJ3U8/CsDHvalRpsxBqivn71ztOFZBTfJMvETbqHiaNSj7Q== + "@types/minimatch@^3.0.3": version "3.0.3" resolved "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d"