vite-plugin-externals
Advanced tools
Comparing version 0.4.0 to 0.5.0
import type { Plugin } from 'vite'; | ||
import { Externals, Options } from './types'; | ||
export declare function viteExternalsPlugin(externals?: Externals, userOptions?: Options): Plugin; | ||
import { Externals, UserOptions } from './types'; | ||
export declare function viteExternalsPlugin(externals?: Externals, userOptions?: UserOptions): Plugin; |
@@ -12,34 +12,37 @@ var __asyncValues = (this && this.__asyncValues) || function (o) { | ||
import { isObject } from './utils'; | ||
import { ensureFile, writeFile, ensureDir, emptyDirSync } from 'fs-extra'; | ||
import { emptyDirSync, ensureDir, ensureFile, writeFile } from 'fs-extra'; | ||
import path from 'path'; | ||
const ID_FILTER_REG = /\.(mjs|js|ts|vue|jsx|tsx)(\?.*|)$/; | ||
const NODE_MODULES_FLAG = 'node_modules'; | ||
const CACHE_DIR = '.vite-plugin-externals'; | ||
import { resolveOptions } from './options'; | ||
import { CACHE_DIR, NODE_MODULES_FLAG } from './constant'; | ||
import { replaceImports, replaceRequires } from './replace'; | ||
export function viteExternalsPlugin(externals = {}, userOptions = {}) { | ||
var _a; | ||
let isBuild = false; | ||
let isServe = false; | ||
const options = resolveOptions(userOptions); | ||
const externalsKeys = Object.keys(externals); | ||
const isExternalEmpty = externalsKeys.length === 0; | ||
const cachePath = path.join(process.cwd(), NODE_MODULES_FLAG, CACHE_DIR); | ||
const transformModuleName = ((useWindow) => { | ||
return (externalValue) => { | ||
if (useWindow === false) { | ||
return typeof externalValue === 'string' ? externalValue : externalValue.join('.'); | ||
} | ||
if (typeof externalValue === 'string') { | ||
return `window['${externalValue}']`; | ||
} | ||
const vals = externalValue.map((val) => `['${val}']`).join(''); | ||
return `window${vals}`; | ||
}; | ||
})((_a = userOptions.useWindow) !== null && _a !== void 0 ? _a : true); | ||
const transformModuleName = (externalValue) => { | ||
const { useWindow } = options; | ||
if (useWindow === false) { | ||
return typeof externalValue === 'string' ? externalValue : externalValue.join('.'); | ||
} | ||
if (typeof externalValue === 'string') { | ||
return `window['${externalValue}']`; | ||
} | ||
const values = externalValue.map((val) => `['${val}']`).join(''); | ||
return `window${values}`; | ||
}; | ||
return { | ||
name: 'vite-plugin-externals', | ||
async config(config, { mode, command }) { | ||
async config(config, { command }) { | ||
var e_1, _a; | ||
var _b, _c, _d; | ||
isBuild = command === 'build'; | ||
if (mode !== 'development') { | ||
isServe = command === 'serve'; | ||
if (!isServe) { | ||
return; | ||
} | ||
if (options.disableInServe) { | ||
return; | ||
} | ||
if (isExternalEmpty) { | ||
@@ -58,2 +61,3 @@ return; | ||
} | ||
const cachePath = path.join(process.cwd(), NODE_MODULES_FLAG, CACHE_DIR); | ||
await ensureDir(cachePath); | ||
@@ -80,7 +84,10 @@ await emptyDirSync(cachePath); | ||
}, | ||
async transform(code, id, options) { | ||
const ssr = compatSsrInOptions(options); | ||
if (!isNeedExternal.call(this, userOptions, code, id, isBuild, ssr)) { | ||
async transform(code, id, _options) { | ||
const ssr = compatSsrInOptions(_options); | ||
if (isServe && options.disableInServe) { | ||
return; | ||
} | ||
if (!isNeedExternal.call(this, options, code, id, isBuild, ssr)) { | ||
return; | ||
} | ||
let s; | ||
@@ -140,34 +147,2 @@ let hasError = false; | ||
} | ||
function replaceRequires(code, externals, transformModuleName) { | ||
return Object.keys(externals).reduce((code, externalKey) => { | ||
const r = new RegExp(`require\\((["'\`])\\s*${externalKey}\\s*(\\1)\\)`, 'g'); | ||
return code.replace(r, transformModuleName(externals[externalKey])); | ||
}, code); | ||
} | ||
function replaceImports(specifiers, externalValue, transformModuleName) { | ||
return specifiers.reduce((s, specifier) => { | ||
const { local } = specifier; | ||
if (specifier.type === 'ImportDefaultSpecifier') { | ||
s += `const ${local.name} = ${transformModuleName(externalValue)}\n`; | ||
} | ||
else if (specifier.type === 'ImportSpecifier') { | ||
const { imported } = specifier; | ||
s += `const ${local.name} = ${transformModuleName(externalValue)}.${imported.name}\n`; | ||
} | ||
else if (specifier.type === 'ImportNamespaceSpecifier') { | ||
s += `const ${local.name} = ${transformModuleName(externalValue)}\n`; | ||
} | ||
else if (specifier.type === 'ExportSpecifier') { | ||
const { exported } = specifier; | ||
const value = `${transformModuleName(externalValue)}${local.name !== 'default' ? `.${local.name}` : ''}`; | ||
if (exported.name === 'default') { | ||
s += `export default ${value}\n`; | ||
} | ||
else { | ||
s += `export const ${exported.name} = ${value}\n`; | ||
} | ||
} | ||
return s; | ||
}, ''); | ||
} | ||
function isNeedExternal(options, code, id, isBuild, ssr) { | ||
@@ -178,14 +153,3 @@ const { disableSsr = true, filter, } = options; | ||
} | ||
if (typeof filter === 'function') { | ||
if (!filter.call(this, code, id, ssr)) { | ||
return false; | ||
} | ||
} | ||
else { | ||
if (!ID_FILTER_REG.test(id) || | ||
(id.includes(NODE_MODULES_FLAG) && !isBuild)) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
return filter.call(this, code, id, ssr !== null && ssr !== void 0 ? ssr : false, isBuild); | ||
} | ||
@@ -192,0 +156,0 @@ function compatSsrInOptions(options) { |
@@ -6,7 +6,10 @@ import { TransformPluginContext } from 'rollup'; | ||
export interface Options { | ||
disableSsr?: boolean; | ||
filter?: (this: TransformPluginContext, code: string, id: string, ssr?: boolean) => boolean; | ||
useWindow?: boolean; | ||
sourceMapOptions?: Partial<SourceMapOptions>; | ||
debug?: boolean; | ||
disableInServe: boolean; | ||
disableSsr: boolean; | ||
filter: (this: TransformPluginContext, code: string, id: string, ssr: boolean, isBuild: boolean) => boolean; | ||
useWindow: boolean; | ||
sourceMapOptions: Partial<SourceMapOptions>; | ||
debug: boolean; | ||
} | ||
export declare type UserOptions = Partial<Options>; | ||
export declare type TransformModuleNameFn = (externalValue: ExternalValue) => string; |
import type { Plugin } from 'vite'; | ||
import { Externals, Options } from './types'; | ||
export declare function viteExternalsPlugin(externals?: Externals, userOptions?: Options): Plugin; | ||
import { Externals, UserOptions } from './types'; | ||
export declare function viteExternalsPlugin(externals?: Externals, userOptions?: UserOptions): Plugin; |
@@ -20,32 +20,35 @@ "use strict"; | ||
const path_1 = __importDefault(require("path")); | ||
const ID_FILTER_REG = /\.(mjs|js|ts|vue|jsx|tsx)(\?.*|)$/; | ||
const NODE_MODULES_FLAG = 'node_modules'; | ||
const CACHE_DIR = '.vite-plugin-externals'; | ||
const options_1 = require("./options"); | ||
const constant_1 = require("./constant"); | ||
const replace_1 = require("./replace"); | ||
function viteExternalsPlugin(externals = {}, userOptions = {}) { | ||
var _a; | ||
let isBuild = false; | ||
let isServe = false; | ||
const options = options_1.resolveOptions(userOptions); | ||
const externalsKeys = Object.keys(externals); | ||
const isExternalEmpty = externalsKeys.length === 0; | ||
const cachePath = path_1.default.join(process.cwd(), NODE_MODULES_FLAG, CACHE_DIR); | ||
const transformModuleName = ((useWindow) => { | ||
return (externalValue) => { | ||
if (useWindow === false) { | ||
return typeof externalValue === 'string' ? externalValue : externalValue.join('.'); | ||
} | ||
if (typeof externalValue === 'string') { | ||
return `window['${externalValue}']`; | ||
} | ||
const vals = externalValue.map((val) => `['${val}']`).join(''); | ||
return `window${vals}`; | ||
}; | ||
})((_a = userOptions.useWindow) !== null && _a !== void 0 ? _a : true); | ||
const transformModuleName = (externalValue) => { | ||
const { useWindow } = options; | ||
if (useWindow === false) { | ||
return typeof externalValue === 'string' ? externalValue : externalValue.join('.'); | ||
} | ||
if (typeof externalValue === 'string') { | ||
return `window['${externalValue}']`; | ||
} | ||
const values = externalValue.map((val) => `['${val}']`).join(''); | ||
return `window${values}`; | ||
}; | ||
return { | ||
name: 'vite-plugin-externals', | ||
async config(config, { mode, command }) { | ||
async config(config, { command }) { | ||
var e_1, _a; | ||
var _b, _c, _d; | ||
isBuild = command === 'build'; | ||
if (mode !== 'development') { | ||
isServe = command === 'serve'; | ||
if (!isServe) { | ||
return; | ||
} | ||
if (options.disableInServe) { | ||
return; | ||
} | ||
if (isExternalEmpty) { | ||
@@ -64,2 +67,3 @@ return; | ||
} | ||
const cachePath = path_1.default.join(process.cwd(), constant_1.NODE_MODULES_FLAG, constant_1.CACHE_DIR); | ||
await fs_extra_1.ensureDir(cachePath); | ||
@@ -86,12 +90,15 @@ await fs_extra_1.emptyDirSync(cachePath); | ||
}, | ||
async transform(code, id, options) { | ||
const ssr = compatSsrInOptions(options); | ||
if (!isNeedExternal.call(this, userOptions, code, id, isBuild, ssr)) { | ||
async transform(code, id, _options) { | ||
const ssr = compatSsrInOptions(_options); | ||
if (isServe && options.disableInServe) { | ||
return; | ||
} | ||
if (!isNeedExternal.call(this, options, code, id, isBuild, ssr)) { | ||
return; | ||
} | ||
let s; | ||
let hasError = false; | ||
try { | ||
if (isBuild && id.includes(NODE_MODULES_FLAG)) { | ||
code = replaceRequires(code, externals, transformModuleName); | ||
if (isBuild && id.includes(constant_1.NODE_MODULES_FLAG)) { | ||
code = replace_1.replaceRequires(code, externals, transformModuleName); | ||
} | ||
@@ -122,3 +129,3 @@ await es_module_lexer_1.init; | ||
} | ||
const newImportStr = replaceImports(specifiers, externalValue, transformModuleName); | ||
const newImportStr = replace_1.replaceImports(specifiers, externalValue, transformModuleName); | ||
s.overwrite(statementStart, statementEnd, newImportStr); | ||
@@ -148,34 +155,2 @@ }); | ||
exports.viteExternalsPlugin = viteExternalsPlugin; | ||
function replaceRequires(code, externals, transformModuleName) { | ||
return Object.keys(externals).reduce((code, externalKey) => { | ||
const r = new RegExp(`require\\((["'\`])\\s*${externalKey}\\s*(\\1)\\)`, 'g'); | ||
return code.replace(r, transformModuleName(externals[externalKey])); | ||
}, code); | ||
} | ||
function replaceImports(specifiers, externalValue, transformModuleName) { | ||
return specifiers.reduce((s, specifier) => { | ||
const { local } = specifier; | ||
if (specifier.type === 'ImportDefaultSpecifier') { | ||
s += `const ${local.name} = ${transformModuleName(externalValue)}\n`; | ||
} | ||
else if (specifier.type === 'ImportSpecifier') { | ||
const { imported } = specifier; | ||
s += `const ${local.name} = ${transformModuleName(externalValue)}.${imported.name}\n`; | ||
} | ||
else if (specifier.type === 'ImportNamespaceSpecifier') { | ||
s += `const ${local.name} = ${transformModuleName(externalValue)}\n`; | ||
} | ||
else if (specifier.type === 'ExportSpecifier') { | ||
const { exported } = specifier; | ||
const value = `${transformModuleName(externalValue)}${local.name !== 'default' ? `.${local.name}` : ''}`; | ||
if (exported.name === 'default') { | ||
s += `export default ${value}\n`; | ||
} | ||
else { | ||
s += `export const ${exported.name} = ${value}\n`; | ||
} | ||
} | ||
return s; | ||
}, ''); | ||
} | ||
function isNeedExternal(options, code, id, isBuild, ssr) { | ||
@@ -186,14 +161,3 @@ const { disableSsr = true, filter, } = options; | ||
} | ||
if (typeof filter === 'function') { | ||
if (!filter.call(this, code, id, ssr)) { | ||
return false; | ||
} | ||
} | ||
else { | ||
if (!ID_FILTER_REG.test(id) || | ||
(id.includes(NODE_MODULES_FLAG) && !isBuild)) { | ||
return false; | ||
} | ||
} | ||
return true; | ||
return filter.call(this, code, id, ssr !== null && ssr !== void 0 ? ssr : false, isBuild); | ||
} | ||
@@ -200,0 +164,0 @@ function compatSsrInOptions(options) { |
@@ -6,7 +6,10 @@ import { TransformPluginContext } from 'rollup'; | ||
export interface Options { | ||
disableSsr?: boolean; | ||
filter?: (this: TransformPluginContext, code: string, id: string, ssr?: boolean) => boolean; | ||
useWindow?: boolean; | ||
sourceMapOptions?: Partial<SourceMapOptions>; | ||
debug?: boolean; | ||
disableInServe: boolean; | ||
disableSsr: boolean; | ||
filter: (this: TransformPluginContext, code: string, id: string, ssr: boolean, isBuild: boolean) => boolean; | ||
useWindow: boolean; | ||
sourceMapOptions: Partial<SourceMapOptions>; | ||
debug: boolean; | ||
} | ||
export declare type UserOptions = Partial<Options>; | ||
export declare type TransformModuleNameFn = (externalValue: ExternalValue) => string; |
{ | ||
"name": "vite-plugin-externals", | ||
"version": "0.4.0", | ||
"version": "0.5.0", | ||
"description": "externals plugin for vite", | ||
@@ -36,3 +36,3 @@ "author": "crcong", | ||
"devDependencies": { | ||
"@crcong/eslint-config-typescript": "^0.1.4", | ||
"@crcong/eslint-config-typescript": "^0.3.0", | ||
"@types/estree": "^0.0.48", | ||
@@ -43,3 +43,3 @@ "@types/fs-extra": "^9.0.12", | ||
"bumpp": "^7.1.1", | ||
"eslint": "^7.28.0", | ||
"eslint": "^8.0.1", | ||
"rimraf": "^3.0.2", | ||
@@ -46,0 +46,0 @@ "rollup": "^2.51.2", |
@@ -41,3 +41,3 @@ # vite-plugin-externals | ||
'react-dom': 'ReactDOM', | ||
// value support chain, tranform to window['React']['lazy'] | ||
// value support chain, transform to window['React']['lazy'] | ||
lazy: ['React', 'lazy'] | ||
@@ -49,4 +49,6 @@ }), | ||
**Warning**: If you loaded `production` libray in `vite dev mode` , may make `HMR` **fail**. | ||
**Warning**: If you loaded `production` library in `vite dev mode` , may make `HMR` **fail**. | ||
You can use `disableInServe: true` option to avoid transform in serve mode. | ||
Eg. | ||
@@ -99,3 +101,3 @@ ```html | ||
plugins: [ | ||
vue(), // @vitejs/plugin-vue will transofrm SFC to JS code | ||
vue(), // @vitejs/plugin-vue will transform SFC to JS code | ||
@@ -112,2 +114,12 @@ // It should be under @vitejs/plugin-vue | ||
### disableInServe | ||
disable transform in `serve mode` . | ||
```js | ||
viteExternalsPlugin({ | ||
vue: 'Vue', | ||
}, { disableInServe: true }) | ||
``` | ||
### filter | ||
@@ -114,0 +126,0 @@ |
@@ -50,2 +50,4 @@ # vite-plugin-externals | ||
你也可以使用 `disableInServe: true` 避免在 serve 模式中转换。 | ||
例如: | ||
@@ -110,2 +112,12 @@ ```html | ||
### disableInServe | ||
在 `serve` 模式中禁止转换 `external` 代码。 | ||
```js | ||
viteExternalsPlugin({ | ||
vue: 'Vue', | ||
}, { disableInServe: true }) | ||
``` | ||
### filter | ||
@@ -112,0 +124,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
32654
29
511
158