feat: make a SWC plugin to emit decorator metadata (#48)
This commit is contained in:
parent
6bae6ac6b4
commit
97ad5fa726
|
@ -50,12 +50,19 @@
|
|||
]
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@swc/core": "^1.0.0",
|
||||
"vite": "^3.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@swc/core": {
|
||||
"optional": true
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@microsoft/api-extractor": "^7.33.5",
|
||||
"@rollup/plugin-node-resolve": "^15.0.1",
|
||||
"@rollup/plugin-typescript": "^9.0.2",
|
||||
"@swc/core": "^1.3.11",
|
||||
"@types/node": "16.18.3",
|
||||
"@typescript-eslint/eslint-plugin": "^5.42.0",
|
||||
"@typescript-eslint/parser": "^5.42.0",
|
||||
|
|
164
pnpm-lock.yaml
164
pnpm-lock.yaml
|
@ -6,6 +6,7 @@ specifiers:
|
|||
'@microsoft/api-extractor': ^7.33.5
|
||||
'@rollup/plugin-node-resolve': ^15.0.1
|
||||
'@rollup/plugin-typescript': ^9.0.2
|
||||
'@swc/core': ^1.3.11
|
||||
'@types/node': 16.18.3
|
||||
'@typescript-eslint/eslint-plugin': ^5.42.0
|
||||
'@typescript-eslint/parser': ^5.42.0
|
||||
|
@ -35,6 +36,7 @@ devDependencies:
|
|||
'@microsoft/api-extractor': 7.33.5
|
||||
'@rollup/plugin-node-resolve': 15.0.1_rollup@2.79.1
|
||||
'@rollup/plugin-typescript': 9.0.2_ee2lsxs7bbggrcawnn34dqpc4e
|
||||
'@swc/core': 1.3.11
|
||||
'@types/node': 16.18.3
|
||||
'@typescript-eslint/eslint-plugin': 5.42.0_6xw5wg2354iw4zujk2f3vyfrzu
|
||||
'@typescript-eslint/parser': 5.42.0_wyqvi574yv7oiwfeinomdzmc3m
|
||||
|
@ -501,6 +503,168 @@ packages:
|
|||
string-argv: 0.3.1
|
||||
dev: true
|
||||
|
||||
/@swc/core-android-arm-eabi/1.3.11:
|
||||
resolution: {integrity: sha512-LC9JlMcdFmTU94KKmQkJKaPSeVmYTfVm2rKGESMiFrgIjopXL/Zeg+XHA97ucnh5iUMkWIpXAMzSOaVRs33K5g==}
|
||||
engines: {node: '>=10'}
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
requiresBuild: true
|
||||
dependencies:
|
||||
'@swc/wasm': 1.2.122
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-android-arm64/1.3.11:
|
||||
resolution: {integrity: sha512-M7FamR3kFpVTyTw73FzKcOZmS7/TWHX75eqtwBTaU9fW4shf0KTLr/h9DnMxNKAnwUMeub/lqlINUe5EKFIKwQ==}
|
||||
engines: {node: '>=10'}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
requiresBuild: true
|
||||
dependencies:
|
||||
'@swc/wasm': 1.2.130
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-darwin-arm64/1.3.11:
|
||||
resolution: {integrity: sha512-LOoiw3uQDuoKBLW3Mn8p6wIccpYjAoDI3ROdto4MksLQSraHMufXY8bqqncfVuy1750XZmC1qnU39RC3yihPfA==}
|
||||
engines: {node: '>=10'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-darwin-x64/1.3.11:
|
||||
resolution: {integrity: sha512-ycjrEbWmpU8MTDdVLdf76ClxQCSTfNqSoP59hieLzhmXpXUa7Oy4sN/v6WSQgp4I1euGs1Wp5kPU5hH5f7XBJQ==}
|
||||
engines: {node: '>=10'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-freebsd-x64/1.3.11:
|
||||
resolution: {integrity: sha512-02uqYktPp6WmZfZ2Crc/yIVOcgANtjo8ciHcT7yLHvz7v+S7gx1I2tyNGUFtTX5hcR2IFNGrL8Yj4DvpTABFHg==}
|
||||
engines: {node: '>=10'}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
requiresBuild: true
|
||||
dependencies:
|
||||
'@swc/wasm': 1.2.130
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-linux-arm-gnueabihf/1.3.11:
|
||||
resolution: {integrity: sha512-nZ2T/gPFncsIiFGhVeVY9vRCTX0hTdqso8OEvFhSwRfRvcEYOpb/rhMG09are7YoB44GMiku5tSzEiNmvT3GuQ==}
|
||||
engines: {node: '>=10'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dependencies:
|
||||
'@swc/wasm': 1.2.130
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-linux-arm64-gnu/1.3.11:
|
||||
resolution: {integrity: sha512-EWEd8NnGwhykEDFIet/r4Fcfr6805ecnBniHZWmG8UVYUp5tz7LYEMZesxCxa0+aGVpCmxHL5/Cdk1uEIrVIzg==}
|
||||
engines: {node: '>=10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-linux-arm64-musl/1.3.11:
|
||||
resolution: {integrity: sha512-ms7CLj2+8sfTM2QnnwqDheYRky9rgPpX2hXmc0KltX+AiSAs7WURjn2JwXWkaICDzXL+djennfswxSspJ53knw==}
|
||||
engines: {node: '>=10'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-linux-x64-gnu/1.3.11:
|
||||
resolution: {integrity: sha512-Fq5/QEY0IbzpIrqlvQT59aMf+nLk//esL3Aj4nvZdsvF4iZaD2oHtXW+/MBi0i1HV9OBWApGZMygYNVS0uVZkQ==}
|
||||
engines: {node: '>=10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-linux-x64-musl/1.3.11:
|
||||
resolution: {integrity: sha512-S/KoEgRHwGhs7VunHiz4jLrnFOJvqZe391j2MiYN1p2EThoGI3rvwcUoHkoxLCXVuDbi4E91qodOheaMGetWNA==}
|
||||
engines: {node: '>=10'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-win32-arm64-msvc/1.3.11:
|
||||
resolution: {integrity: sha512-fFby7KOQIxolR6w4Gie8MSkgQ3ee6j3r7A6PX4ekzu+509QsZogLPZnWFTJ8WFo7ui0tx/ocA5X8BV4ZNBVlKQ==}
|
||||
engines: {node: '>=10'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dependencies:
|
||||
'@swc/wasm': 1.2.130
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-win32-ia32-msvc/1.3.11:
|
||||
resolution: {integrity: sha512-fii7Y33S9Z5oZ/BTsXa8Ou/RZ4T/ZsAOFpG7mMvifpdAP6LVWdhLoNy7SeeEHTEAWGcWNA/FslA6p2WETvEEfA==}
|
||||
engines: {node: '>=10'}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dependencies:
|
||||
'@swc/wasm': 1.2.130
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core-win32-x64-msvc/1.3.11:
|
||||
resolution: {integrity: sha512-cDF4qBQLf3U0KypnLn3T1HtE12QmEplPGjWs2Xd/hzVkjsPixVR8XIgLlczsj7Pk7Of7VDnUDLIl52aIdgTm8w==}
|
||||
engines: {node: '>=10'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/core/1.3.11:
|
||||
resolution: {integrity: sha512-lnCnnnNCsnbrhW/gwkoN0sAeIqOyoHLS4ZB20xmPJjKVfvTnJrAcNnLSiwlYdcoUSFqT2GYZjUAG6usEzRQASA==}
|
||||
engines: {node: '>=10'}
|
||||
hasBin: true
|
||||
requiresBuild: true
|
||||
optionalDependencies:
|
||||
'@swc/core-android-arm-eabi': 1.3.11
|
||||
'@swc/core-android-arm64': 1.3.11
|
||||
'@swc/core-darwin-arm64': 1.3.11
|
||||
'@swc/core-darwin-x64': 1.3.11
|
||||
'@swc/core-freebsd-x64': 1.3.11
|
||||
'@swc/core-linux-arm-gnueabihf': 1.3.11
|
||||
'@swc/core-linux-arm64-gnu': 1.3.11
|
||||
'@swc/core-linux-arm64-musl': 1.3.11
|
||||
'@swc/core-linux-x64-gnu': 1.3.11
|
||||
'@swc/core-linux-x64-musl': 1.3.11
|
||||
'@swc/core-win32-arm64-msvc': 1.3.11
|
||||
'@swc/core-win32-ia32-msvc': 1.3.11
|
||||
'@swc/core-win32-x64-msvc': 1.3.11
|
||||
dev: true
|
||||
|
||||
/@swc/wasm/1.2.122:
|
||||
resolution: {integrity: sha512-sM1VCWQxmNhFtdxME+8UXNyPNhxNu7zdb6ikWpz0YKAQQFRGT5ThZgJrubEpah335SUToNg8pkdDF7ibVCjxbQ==}
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@swc/wasm/1.2.130:
|
||||
resolution: {integrity: sha512-rNcJsBxS70+pv8YUWwf5fRlWX6JoY/HJc25HD/F8m6Kv7XhJdqPPMhyX6TKkUBPAG7TWlZYoxa+rHAjPy4Cj3Q==}
|
||||
requiresBuild: true
|
||||
dev: true
|
||||
optional: true
|
||||
|
||||
/@types/argparse/1.0.38:
|
||||
resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==}
|
||||
dev: true
|
||||
|
|
|
@ -5,3 +5,4 @@ export { build } from './build'
|
|||
export { preview } from './preview'
|
||||
export * from './plugin'
|
||||
export { compileToBytecode } from './bytecode'
|
||||
export * from './swc'
|
||||
|
|
112
src/swc.ts
Normal file
112
src/swc.ts
Normal file
|
@ -0,0 +1,112 @@
|
|||
import { createRequire } from 'node:module'
|
||||
import type { SourceMap } from 'rollup'
|
||||
import type { TransformConfig, Output as TransformResult, JscConfig } from '@swc/core'
|
||||
import type { Plugin, UserConfig, FilterPattern } from 'vite'
|
||||
import { createFilter } from 'vite'
|
||||
|
||||
type SwcTransformResult = Omit<TransformResult, 'map'> & {
|
||||
map: SourceMap
|
||||
}
|
||||
|
||||
type SwcTransformOptions = {
|
||||
sourcemap?: boolean | 'inline' | undefined
|
||||
minify?: boolean
|
||||
} & TransformConfig
|
||||
|
||||
async function transformWithSWC(code: string, id: string, options: SwcTransformOptions): Promise<SwcTransformResult> {
|
||||
const { sourcemap = false, minify = false } = options
|
||||
|
||||
delete options.sourcemap
|
||||
delete options.minify
|
||||
|
||||
const isTs = /\.tsx?$/.test(id)
|
||||
|
||||
const require = createRequire(import.meta.url)
|
||||
|
||||
const swc: typeof import('@swc/core') = require('@swc/core')
|
||||
|
||||
if (!swc) {
|
||||
throw new Error('swc plugin require @swc/core, you need to install it.')
|
||||
}
|
||||
|
||||
const jsc: JscConfig = {
|
||||
parser: {
|
||||
syntax: isTs ? 'typescript' : 'ecmascript',
|
||||
decorators: true
|
||||
},
|
||||
transform: {
|
||||
legacyDecorator: true,
|
||||
decoratorMetadata: true,
|
||||
...options
|
||||
},
|
||||
keepClassNames: true,
|
||||
target: 'es2022',
|
||||
minify: {
|
||||
format: {
|
||||
comments: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const result = await swc.transform(code, {
|
||||
jsc,
|
||||
sourceMaps: sourcemap,
|
||||
minify,
|
||||
configFile: false,
|
||||
swcrc: false
|
||||
})
|
||||
|
||||
const map: SourceMap = sourcemap && result.map ? JSON.parse(result.map) : { mappings: '' }
|
||||
|
||||
return {
|
||||
code: result.code,
|
||||
map
|
||||
}
|
||||
}
|
||||
|
||||
export type SwcOptions = {
|
||||
include?: FilterPattern
|
||||
exclude?: FilterPattern
|
||||
transformOptions?: TransformConfig
|
||||
}
|
||||
|
||||
export function swcPlugin(options: SwcOptions = {}): Plugin {
|
||||
const filter = createFilter(options.include || /\.(m?ts|[jt]sx)$/, options.exclude || /\.js$/)
|
||||
let sourcemap: boolean | 'inline' = false
|
||||
let minify: boolean | 'esbuild' | 'terser' = false
|
||||
return {
|
||||
name: 'vite:swc',
|
||||
config(): UserConfig {
|
||||
return {
|
||||
esbuild: false
|
||||
}
|
||||
},
|
||||
async configResolved(resolvedConfig): Promise<void> {
|
||||
sourcemap = resolvedConfig.build?.sourcemap === 'inline' ? 'inline' : !!resolvedConfig.build?.sourcemap
|
||||
minify = resolvedConfig.build?.minify
|
||||
},
|
||||
async transform(code, id): Promise<void | { code: string; map: SourceMap }> {
|
||||
if (filter(id)) {
|
||||
const result = await transformWithSWC(code, id, { sourcemap, ...(options.transformOptions || {}) })
|
||||
return {
|
||||
code: result.code,
|
||||
map: result.map
|
||||
}
|
||||
}
|
||||
},
|
||||
async renderChunk(code, chunk): Promise<null | { code: string; map: SourceMap }> {
|
||||
if (!minify || minify === 'terser') {
|
||||
return null
|
||||
}
|
||||
const result = await transformWithSWC(code, chunk.fileName, {
|
||||
sourcemap,
|
||||
minify: true,
|
||||
...(options.transformOptions || {})
|
||||
})
|
||||
return {
|
||||
code: result.code,
|
||||
map: result.map
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue