rollup-plugin-fast-typescript
Advanced tools
Comparing version 2.0.0 to 2.1.0
import type { Plugin, MaybePromise } from 'rollup'; | ||
import ts from 'typescript'; | ||
export interface TsConfigJson { | ||
/** | ||
* Path to base configuration file to inherit from (requires TypeScript version 2.1 or later), | ||
* or array of base files, with the rightmost files having the greater priority (requires TypeScript version 5.0 or later). | ||
*/ | ||
extends?: string | string[]; | ||
/** | ||
* Specifies a list of glob patterns that match files to be included in compilation. | ||
* If no 'files' or 'include' property is present in a tsconfig.json, | ||
* the compiler defaults to including all files in the containing directory and subdirectories | ||
* except those specified by 'exclude'. Requires TypeScript version 2.0 or later. | ||
*/ | ||
include?: string[]; | ||
/** | ||
* Specifies a list of files to be excluded from compilation. | ||
* The 'exclude' property only affects the files included via the 'include' property and not the 'files' property. | ||
* Glob patterns require TypeScript version 2.0 or later. | ||
*/ | ||
exclude?: string[]; | ||
/** | ||
* If no 'files' or 'include' property is present in a tsconfig.json, | ||
* the compiler defaults to including all files in the containing directory and subdirectories | ||
* except those specified by 'exclude'. When a 'files' property is specified, | ||
* only those files and those specified by 'include' are included. | ||
*/ | ||
files?: string[]; | ||
/** Instructs the TypeScript compiler how to compile `.ts` files. */ | ||
compilerOptions?: ts.CompilerOptions; | ||
/** Settings for the watch mode in TypeScript. */ | ||
watchOptions?: ts.WatchOptions; | ||
/** Auto type (.d.ts) acquisition options for this project. Requires TypeScript version 2.1 or later. */ | ||
typeAcquisition?: ts.TypeAcquisition; | ||
/** Enable Compile-on-Save for this project. */ | ||
compileOnSave?: boolean; | ||
/** Referenced projects. Requires TypeScript version 3.0 or later. */ | ||
references?: ts.ProjectReference[]; | ||
} | ||
import type { TsConfigJson } from 'type-fest'; | ||
export { TsConfigJson }; | ||
/** | ||
* A plugin that uses esbuild, swc or sucrase for blazing fast TypeScript transforms, | ||
* leaving the bundling task to Rollup. | ||
* A plugin that uses esbuild, swc or sucrase for blazing fast TypeScript transforms. | ||
*/ | ||
export declare function fastTypescript(transformerName: 'esbuild' | 'swc' | 'sucrase', tsConfigJson?: boolean | string | TsConfigJson | (() => MaybePromise<boolean | string | TsConfigJson>)): Plugin; | ||
export declare function fastTypescript(transpiler: 'esbuild' | 'swc' | 'sucrase', tsConfig?: boolean | string | TsConfigJson | (() => MaybePromise<boolean | string | TsConfigJson>)): Plugin; | ||
/** A plugin that uses esbuild for blazing fast TypeScript transforms. */ | ||
export declare function esbuild(tsConfig?: boolean | string | TsConfigJson | (() => MaybePromise<boolean | string | TsConfigJson>)): Plugin; | ||
/** A plugin that uses swc for blazing fast TypeScript transforms. */ | ||
export declare function swc(tsConfig?: boolean | string | TsConfigJson | (() => MaybePromise<boolean | string | TsConfigJson>)): Plugin; | ||
/** A plugin that uses sucrase for blazing fast TypeScript transforms. */ | ||
export declare function sucrase(tsConfig?: boolean | string | TsConfigJson | (() => MaybePromise<boolean | string | TsConfigJson>)): Plugin; | ||
export default fastTypescript; |
@@ -5,7 +5,4 @@ import { createRequire } from 'node:module'; | ||
import { isTsSourceFile, isTsDeclarationFile } from './transformers/_lib.js'; | ||
/** | ||
* A plugin that uses esbuild, swc or sucrase for blazing fast TypeScript transforms, | ||
* leaving the bundling task to Rollup. | ||
*/ | ||
export function fastTypescript(transformerName, tsConfigJson = true) { | ||
const self = createRequire(import.meta.url)('../package.json'); | ||
export function fastTypescript(transpiler, tsConfig = true) { | ||
function tsDiagnosticAsText(diagnostic) { | ||
@@ -17,31 +14,22 @@ const { messageText } = diagnostic; | ||
} | ||
const { version, homepage } = createRequire(import.meta.url)('../package.json'); | ||
let transformer; | ||
let tsCompilerOptions; | ||
let tsModuleResolutionCache; | ||
let resolveIdCache; | ||
let transformer; | ||
return { | ||
name: 'fast-typescript', | ||
version: version, | ||
name: self.name.replace(/^rollup-plugin-/, ''), | ||
version: self.version, | ||
async buildStart() { | ||
// Check the transformer name. | ||
if (transformerName !== 'esbuild' && transformerName !== 'swc' && transformerName !== 'sucrase') { | ||
this.error({ | ||
message: transformerName | ||
? `Unknown transformer ${JSON.stringify(transformerName)}` | ||
: 'Missing transformer name in plugin options.', | ||
stack: undefined | ||
}); | ||
} | ||
// Resolve the tsconfig option. | ||
if (typeof tsConfigJson === 'function') | ||
tsConfigJson = await tsConfigJson() ?? true; | ||
if (tsConfigJson === true) | ||
tsConfigJson = './tsconfig.json'; | ||
else if (tsConfigJson === false || tsConfigJson === '') | ||
tsConfigJson = { compilerOptions: {} }; | ||
else if (typeof tsConfigJson !== 'string' && typeof tsConfigJson !== 'object') | ||
this.error({ message: `Invalid value '${JSON.stringify(tsConfigJson)}' for tsconfig parameter.`, stack: undefined }); | ||
// Use the TypeScript API to load and parse the full tsconfig.json chain, | ||
// including extended configs, paths resolution, etc. | ||
if (typeof transpiler !== 'string' || !transpiler) | ||
this.error({ message: 'Missing or invalid transpiler name in plugin options.', stack: undefined }); | ||
else if (transpiler !== 'esbuild' && transpiler !== 'swc' && transpiler !== 'sucrase') | ||
this.error({ message: `Unknown transpiler ${JSON.stringify(transpiler)}`, stack: undefined }); | ||
if (typeof tsConfig === 'function') | ||
tsConfig = await tsConfig(); | ||
if (tsConfig === true) | ||
tsConfig = './tsconfig.json'; | ||
else if (!tsConfig) | ||
tsConfig = {}; | ||
else if (typeof tsConfig !== 'string' && typeof tsConfig !== 'object') | ||
this.error({ message: `Invalid value '${JSON.stringify(tsConfig)}' for tsConfig parameter.`, stack: undefined }); | ||
const configFileChain = []; | ||
@@ -52,22 +40,30 @@ const parseConfigHost = { | ||
readDirectory: ts.sys.readDirectory, | ||
readFile: file => (!file.endsWith('package.json') && configFileChain.push(path.normalize(file)), | ||
ts.sys.readFile(file)) | ||
readFile(file) { | ||
if (path.basename(file) !== 'package.json') | ||
configFileChain.push(path.normalize(file)); | ||
return ts.sys.readFile(file); | ||
} | ||
}; | ||
let tsConfigBasePath; | ||
let tsConfig; | ||
let tsDiagnostics; | ||
if (typeof tsConfigJson === 'string') { | ||
tsConfigJson = path.resolve(tsConfigJson); | ||
tsConfigBasePath = path.dirname(tsConfigJson); | ||
configFileChain.push(tsConfigJson); | ||
const { config, error } = ts.readConfigFile(tsConfigJson, ts.sys.readFile); | ||
if (error) | ||
tsDiagnostics = [error]; | ||
tsConfig = ts.parseJsonConfigFileContent(config, parseConfigHost, tsConfigBasePath); | ||
let tsConfigBasePath, tsConfigParsed, tsDiagnostics = []; | ||
if (typeof tsConfig === 'string') { | ||
tsConfig = path.resolve(tsConfig); | ||
tsConfigBasePath = path.dirname(tsConfig); | ||
configFileChain.push(tsConfig); | ||
const { config, error } = ts.readConfigFile(tsConfig, ts.sys.readFile); | ||
if (error) { | ||
tsDiagnostics.push(error); | ||
tsConfigParsed = { | ||
options: {}, | ||
fileNames: [], | ||
errors: [error] | ||
}; | ||
} | ||
else | ||
tsConfigParsed = ts.parseJsonConfigFileContent(config, parseConfigHost, tsConfigBasePath, undefined, path.basename(tsConfig)); | ||
} | ||
else { | ||
tsConfigBasePath = process.cwd(); | ||
tsConfig = ts.parseJsonConfigFileContent(tsConfigJson, parseConfigHost, tsConfigBasePath, /* existingOptions */ undefined, /* configFileName */ '<configObject>'); | ||
tsConfigParsed = ts.parseJsonConfigFileContent(tsConfig, parseConfigHost, tsConfigBasePath, undefined, '<configObject>'); | ||
} | ||
tsDiagnostics ??= ts.getConfigFileParsingDiagnostics(tsConfig); | ||
tsDiagnostics.push(...ts.getConfigFileParsingDiagnostics(tsConfigParsed)); | ||
if (tsDiagnostics.length) { | ||
@@ -78,15 +74,14 @@ const error = tsDiagnostics.find(diag => diag.category === ts.DiagnosticCategory.Error); | ||
else { | ||
tsDiagnostics.filter(diag => diag.category === ts.DiagnosticCategory.Warning).forEach(diag => { | ||
this.warn(tsDiagnosticAsText(diag)); | ||
tsDiagnostics.forEach(diag => { | ||
if (diag.category === ts.DiagnosticCategory.Warning) | ||
this.warn(tsDiagnosticAsText(diag)); | ||
}); | ||
} | ||
} | ||
// Add our own "diagnostics" | ||
tsCompilerOptions = tsConfig.options; | ||
tsCompilerOptions = tsConfigParsed.options; | ||
if (!tsCompilerOptions.isolatedModules) { | ||
tsCompilerOptions.isolatedModules = true; | ||
this.warn(`'compilerOptions.isolatedModules' should be set to true in tsconfig. See ${new URL('#isolatedmodules', homepage).href} for details.`); | ||
this.warn(`'compilerOptions.isolatedModules' should be set to true in tsconfig. See ${new URL('#isolatedmodules', self.homepage).href} for details.`); | ||
} | ||
// Lazy-load the transformer then hand off the tsconfig. | ||
transformer = await import(`./transformers/${transformerName}.js`) | ||
transformer = await import(`./transformers/${transpiler}.js`) | ||
.then(plugin => plugin.default) | ||
@@ -96,3 +91,3 @@ .catch(({ code, message }) => { | ||
message: code === 'ERR_MODULE_NOT_FOUND' | ||
? `Transformer '${transformerName}' could not be loaded, reinstalling this plugin might fix the error.` | ||
? `Transformer '${transpiler}' could not be loaded, reinstalling this plugin might fix the error.` | ||
: message, | ||
@@ -103,18 +98,14 @@ stack: undefined | ||
transformer.applyCompilerOptions(this, tsCompilerOptions); | ||
// Initialize both TypeScript's and our own resolution cache. | ||
resolveIdCache = new Map(); | ||
tsModuleResolutionCache = ts.createModuleResolutionCache(tsConfigBasePath, _ => _, tsCompilerOptions); | ||
// And finally, watch the whole config chain. | ||
if (this.meta.watchMode) { | ||
for (const file of configFileChain) { | ||
this.addWatchFile(file); | ||
} | ||
for (const file of configFileChain) { | ||
this.addWatchFile(file); | ||
} | ||
}, | ||
async resolveId(id, importer, { isEntry }) { | ||
if (!importer || isEntry || !isTsSourceFile(importer) || id.startsWith('\0')) | ||
async resolveId(id, importer) { | ||
if (!importer | ||
|| !isTsSourceFile(importer) | ||
|| id.startsWith('\0')) { | ||
return null; | ||
// Some plugins sometimes cause the resolver to be called multiple times for the same id, | ||
// so we cache our results for faster response when this happens. | ||
// (undefined = not seen before, null = not handled by us, string = resolved) | ||
} | ||
let resolved = resolveIdCache.get(id); | ||
@@ -140,3 +131,12 @@ if (resolved !== undefined) | ||
} | ||
export function esbuild(tsConfig = true) { | ||
return fastTypescript('esbuild', tsConfig); | ||
} | ||
export function swc(tsConfig = true) { | ||
return fastTypescript('swc', tsConfig); | ||
} | ||
export function sucrase(tsConfig = true) { | ||
return fastTypescript('sucrase', tsConfig); | ||
} | ||
export default fastTypescript; | ||
//# sourceMappingURL=index.js.map |
@@ -9,7 +9,6 @@ const tsExtensions = new Set(['.ts', '.tsx', '.mts', '.cts']); | ||
} | ||
// Like path.extname() but accounts for multiple extensions (ie., `extname('index.d.ts') -> '.d.ts')`. | ||
export function extname(pathname) { | ||
pathname = pathname.split(/[\\/]/) // Split path parts | ||
.pop() // Get basename | ||
.replace(/^\.+/, dots => '-'.repeat(dots.length)); // Ignore starting dot(s): extname('.config.rc') -> '.rc' | ||
pathname = pathname.split(/[\\/]/) | ||
.pop() | ||
.replace(/^\.+/, dots => '-'.repeat(dots.length)); | ||
const dot = pathname.indexOf('.'); | ||
@@ -16,0 +15,0 @@ return dot >= 0 ? pathname.slice(dot) : ''; |
@@ -22,19 +22,16 @@ import esbuild from 'esbuild'; | ||
let { target, jsx = ts.JsxEmit.None } = compilerOptions; | ||
// In esbuild, `target` defaults to 'esnext' if not given while it defaults to 'es3' in TypeScript. | ||
// Therefore, to get TypeScript's behavior, we must set the option explicitly if not present. | ||
let es3Warning = ''; | ||
const es3Warning = []; | ||
if (target === undefined) { | ||
target = ts.ScriptTarget.ES3; | ||
es3Warning = "'target' property is not set in tsconfig and so it defaults to ES3 in TypeScript. " + | ||
"However, "; | ||
if (parseFloat(ts.version) < 5.0) { | ||
es3Warning.push("When the 'target' property is not set in tsconfig.json, ", `it defaults to ES3 in TypeScript ${ts.version}. `, "However, "); | ||
target = ts.ScriptTarget.ES3; | ||
} | ||
else | ||
target = ts.ScriptTarget.ES5; | ||
} | ||
if (target === ts.ScriptTarget.ES3) { | ||
context.warn(es3Warning + [ | ||
"ES3 target is not supported by esbuild, so ES5 will be used instead.", | ||
"Please set 'target' option in tsconfig to at least ES5 to disable this warning or,", | ||
"if you really need ES3 output, use either swc or sucrase rather than esbuild." | ||
].join(' ')); | ||
es3Warning.push("ES3 target is not supported by esbuild, so ES5 will be used instead.\n", "Please set the 'target' option in tsconfig.json to at least ES5 to disable this warning or, ", "if you really need ES3 output, use either swc or sucrase rather than esbuild."); | ||
context.warn(es3Warning.join('')); | ||
target = ts.ScriptTarget.ES5; | ||
} | ||
// Prepare options. | ||
transformOptions = { | ||
@@ -74,4 +71,2 @@ format: 'esm', | ||
for (const warning of warnings) { | ||
// Because we're transforming to ESM, esbuild will emit this warning | ||
// if the source code contains require() calls. Silent them. | ||
if (warning.text.startsWith('Converting "require" to "esm"')) | ||
@@ -78,0 +73,0 @@ continue; |
@@ -11,2 +11,3 @@ import sucrase from 'sucrase'; | ||
preserveDynamicImport: true, | ||
keepUnusedImports: compilerOptions.verbatimModuleSyntax, | ||
injectCreateRequireForImportRequire: false, | ||
@@ -25,5 +26,5 @@ enableLegacyTypeScriptModuleInterop: compilerOptions.esModuleInterop === false, | ||
}, | ||
async transform(context, sourcecode, filePath) { | ||
transform(context, sourcecode, filePath) { | ||
try { | ||
const { code, sourceMap: map } = sucrase.transform(sourcecode, { | ||
const { code, sourceMap } = sucrase.transform(sourcecode, { | ||
...transformOptions, | ||
@@ -35,3 +36,3 @@ filePath, | ||
}); | ||
return { code, map }; | ||
return { code, map: sourceMap }; | ||
} | ||
@@ -38,0 +39,0 @@ catch (err) { |
import swc from '@swc/core'; | ||
import ts from 'typescript'; | ||
import { extname } from './_lib.js'; | ||
let preserveJsx; | ||
let reactConfig; | ||
let transformConfig; | ||
let parserConfig; | ||
let transformConfig; | ||
let reactConfig; | ||
let swcOptions; | ||
let preserveJsx; | ||
export default { | ||
applyCompilerOptions(context, compilerOptions) { | ||
const { target = ts.ScriptTarget.ES3, jsx = ts.JsxEmit.None } = compilerOptions; | ||
const { target = parseFloat(ts.version) >= 5.0 ? ts.ScriptTarget.ES5 : ts.ScriptTarget.ES3, jsx = ts.JsxEmit.None } = compilerOptions; | ||
preserveJsx = jsx === ts.JsxEmit.None || | ||
jsx === ts.JsxEmit.Preserve || | ||
jsx === ts.JsxEmit.ReactNative; | ||
// swcOptions.jsc.transform.react | ||
reactConfig = { | ||
runtime: ts.JsxEmit.ReactJSX ? 'automatic' : 'classic', | ||
runtime: jsx === ts.JsxEmit.React ? 'classic' : 'automatic', | ||
development: jsx === ts.JsxEmit.ReactJSXDev, | ||
@@ -24,3 +23,2 @@ pragma: compilerOptions.jsxFactory, | ||
}; | ||
// swcOptions.jsc.transform | ||
transformConfig = { | ||
@@ -31,3 +29,2 @@ decoratorMetadata: compilerOptions.emitDecoratorMetadata, | ||
}; | ||
// swcOptions.jsc.parser | ||
parserConfig = { | ||
@@ -38,3 +35,2 @@ syntax: 'typescript', | ||
}; | ||
// swcOptions | ||
swcOptions = { | ||
@@ -46,4 +42,4 @@ configFile: false, | ||
type: 'es6', | ||
strict: false, // no __esModule | ||
strictMode: false, // no 'use strict'; | ||
strict: false, | ||
strictMode: false, | ||
importInterop: 'none', | ||
@@ -58,3 +54,3 @@ ignoreDynamic: true, | ||
jsc: { | ||
target: (target === ts.ScriptTarget.ES2015 // swc doest not have 'es6' as a target | ||
target: (target === ts.ScriptTarget.ES2015 | ||
? 'es2015' | ||
@@ -76,8 +72,15 @@ : target === ts.ScriptTarget.ESNext | ||
async transform(context, sourcecode, sourcefile) { | ||
const isTsx = extname(sourcefile) === '.tsx'; | ||
parserConfig.tsx = isTsx; | ||
transformConfig.react = isTsx && !preserveJsx | ||
? reactConfig | ||
: undefined; | ||
return (swc.transform(sourcecode, swcOptions) | ||
parserConfig.tsx = extname(sourcefile) === '.tsx'; | ||
if (parserConfig.tsx) { | ||
transformConfig.react = reactConfig; | ||
if (preserveJsx) { | ||
context.error({ | ||
message: "swc cannot preserve JSX syntax. Please set the 'jsx' setting in tsconfig.json to either 'react', 'react-jsx' or 'react-jsxdev'.", | ||
stack: undefined | ||
}); | ||
} | ||
} | ||
else | ||
transformConfig.react = undefined; | ||
return swc.transform(sourcecode, swcOptions) | ||
.catch(err => { | ||
@@ -91,5 +94,5 @@ const message = (err instanceof Error | ||
return null; | ||
})); | ||
}); | ||
} | ||
}; | ||
//# sourceMappingURL=swc.js.map |
{ | ||
"name": "rollup-plugin-fast-typescript", | ||
"version": "2.0.0", | ||
"description": "A plugin that uses esbuild, swc or sucrase (you decide!) for blazing fast TypeScript transpilation, leaving the tree-shaking and bundling tasks to Rollup.", | ||
"version": "2.1.0", | ||
"description": "A plugin that uses esbuild, swc or sucrase (you decide!) for blazing fast TypeScript transpilation.", | ||
"author": "Stephan 'Septh' Schreiber <septh@sfr.fr>", | ||
@@ -15,9 +15,8 @@ "keywords": [ | ||
"license": "MIT", | ||
"homepage": "https://github.com/Septh/rollup-plugins/tree/main/plugins/fast-typescript#readme", | ||
"homepage": "https://github.com/Septh/rollup-plugin-fast-typescript#readme", | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/Septh/rollup-plugins.git", | ||
"directory": "plugins/fast-typescript" | ||
"url": "https://github.com/Septh/rollup-plugin-fast-typescript.git" | ||
}, | ||
"bugs": "https://github.com/Septh/rollup-plugins/issues", | ||
"bugs": "https://github.com/Septh/rollup-plugin-fast-typescript/issues", | ||
"files": [ | ||
@@ -36,13 +35,14 @@ "build", | ||
"scripts": { | ||
"prebuild": "npm run clean", | ||
"clean": "rimraf build", | ||
"build": "tsc", | ||
"watch": "npm run build -- --watch", | ||
"build": "rimraf build && tsc", | ||
"watch": "rimraf build && tsc --watch", | ||
"check": "tsc --noEmit --skipLibCheck", | ||
"changelog": "changelog" | ||
"prepublishOnly": "rimraf build && tsc --removeComments --declaration false && tsc --emitDeclarationOnly" | ||
}, | ||
"dependencies": { | ||
"type-fest": "^0.13.1" | ||
}, | ||
"peerDependencies": { | ||
"@swc/core": "^1.3.100", | ||
"esbuild": ">=0.18.0", | ||
"rollup": "^4.0.0", | ||
"rollup": "^4.17.0", | ||
"sucrase": "^3.35.0", | ||
@@ -63,12 +63,10 @@ "typescript": "^5.3.0" | ||
"devDependencies": { | ||
"@septh/changelog": "^1.0.0", | ||
"@swc/core": "^1.3.106", | ||
"esbuild": "^0.20.0", | ||
"@swc/core": "^1.4.17", | ||
"@types/node": "^20.12.7", | ||
"esbuild": "^0.20.2", | ||
"sucrase": "^3.35.0", | ||
"typescript": "^5.3.3" | ||
}, | ||
"np": { | ||
"yarn": false, | ||
"clean": false | ||
"rollup": "^4.17.0", | ||
"tslib": "^2.6.2", | ||
"typescript": "^5.4.5" | ||
} | ||
} |
112
README.md
# rollup-plugin-fast-typescript | ||
A plugin that uses esbuild, swc or sucrase (you decide!) for blazing fast TypeScript transpilation, leaving the tree-shaking and bundling tasks to Rollup (see [why](#considerations)). | ||
A plugin that uses esbuild, swc or Sucrase (you decide!) for blazing fast TypeScript transpilation. | ||
>⚠ Important notice | ||
>- This plugin requires rollup version 4.0.0 or higher. | ||
>- This package is ESM-only and can only be used from an ESM configuration file (`rollup.config.mjs` or `rollup.config.js` with `type="module"` in `package.json`. See [Rollup docs](https://rollupjs.org/guide/en/#configuration-files) for more detail). | ||
>- This plugin requires Rollup version 4.0.0 or higher. | ||
>- This package is ESM-only and can only be used from an ESM configuration file (either `rollup.config.mjs` or `rollup.config.js` with `type="module"` in `package.json`. See [Rollup docs](https://rollupjs.org/guide/en/#configuration-files) for more detail). | ||
## Features | ||
- You choose which one of the three supported transpilers to use. | ||
- Zero config: your project's `tsconfig.json` is all you need go get started. | ||
- Zero config: your project's `tsconfig.json` is all you need. | ||
- Uses TypeScript API for full `tsconfig.json` compatibility: | ||
@@ -16,3 +15,3 @@ - `tsconfig.json#extends`: | ||
- Full TypeScript-like module resolution, including `compilerOptions#baseUrl`, `compilerOptions#paths`, `compilerOptions#rootDirs` and even `compilerOptions#moduleSuffixes`! | ||
- No "magic" that happens behind your back. Everything is under *your* control. | ||
- No hidden "magic" that happens behind your back. | ||
@@ -24,11 +23,15 @@ ## Installation | ||
For esbuild: | ||
```sh | ||
# for esbuild: | ||
npm install --save-dev rollup rollup-plugin-fast-typescript esbuild | ||
npm install --save-dev rollup-plugin-fast-typescript esbuild | ||
``` | ||
# for swc: | ||
npm install --save-dev rollup rollup-plugin-fast-typescript @swc/core | ||
For swc: | ||
```sh | ||
npm install --save-dev rollup-plugin-fast-typescript @swc/core | ||
``` | ||
# for sucrase: | ||
npm install --save-dev rollup rollup-plugin-fast-typescript sucrase | ||
For Sucrase: | ||
```sh | ||
npm install --save-dev rollup-plugin-fast-typescript sucrase | ||
``` | ||
@@ -40,3 +43,3 @@ | ||
```js | ||
// rollup.config.mjs | ||
// rollup.config.js | ||
import fastTypescript from 'rollup-plugin-fast-typescript' | ||
@@ -54,8 +57,27 @@ | ||
Starting with version 2.1.0, the plugin also exports these three convenience functions: | ||
* `esbuild(tsconfig)` is an alias for `fastTypescript('esbuild', tsconfig)` | ||
* `swc(tsconfig)` is an alias for `fastTypescript('swc', tsconfig)` | ||
* `sucrase(tsconfig)` is an alias for `fastTypescript('sucrase', tsconfig)` | ||
For example: | ||
```js | ||
// rollup.config.js | ||
import { swc } from 'rollup-plugin-fast-typescript' | ||
export default { | ||
... | ||
plugins: [ | ||
swc() // Use swc to transpile TypeScript | ||
] | ||
} | ||
``` | ||
## Options | ||
`rollup-plugin-fast-typescript`'s *parti pris* is to mimic the behavior of the real TypeScript compiler as closely as possible (two obvious exceptions here are type checking and declaration files generation, since none of the supported transpilers support these features), so the plugin doest not offer any option to play with other than the choice of the transpiler to use and the tsconfig file to load. | ||
`rollup-plugin-fast-typescript`'s *parti pris* is to mimic the behavior of the real TypeScript compiler as closely as possible (two obvious exceptions here are type checking and declaration files generation, since none of the supported transpilers support these features), so the plugin doest not offer any option to play with other than the choice of the transpiler to use and the `tsconfig.json` settings to use. | ||
```js | ||
fastTypescript( | ||
transpilerName : 'esbuild' | 'swc' | 'sucrase', | ||
transpiler : 'esbuild' | 'swc' | 'sucrase', | ||
tsconfig?: boolean | string | TsConfigJson | (() => MaybePromise<boolean | string | TsConfigJson>) | ||
@@ -65,8 +87,27 @@ ) | ||
```js | ||
esbuild( | ||
tsconfig?: boolean | string | TsConfigJson | (() => MaybePromise<boolean | string | TsConfigJson>) | ||
) | ||
``` | ||
```js | ||
swc( | ||
tsconfig?: boolean | string | TsConfigJson | (() => MaybePromise<boolean | string | TsConfigJson>) | ||
) | ||
``` | ||
```js | ||
sucrase( | ||
tsconfig?: boolean | string | TsConfigJson | (() => MaybePromise<boolean | string | TsConfigJson>) | ||
) | ||
``` | ||
### Option: `transpiler` | ||
Type: `'esbuild' | 'swc' | 'sucrase'` | ||
Type: `'esbuild' | 'swc' | 'sucrase'`<br> | ||
Optional: no | ||
The name of the transpiler to use. | ||
When using the generic `fastTypescript` export, you must specify the name of the transpiler to use. | ||
> Remember that this plugin does not ship with, nor will it install for you, any of these transpilers; it is your responsibility to install the tool you plan to use. | ||
> Again, remember that this plugin does not ship with, nor will it install for you, any of these transpilers; it is your responsibility to install the tool you plan to use. | ||
@@ -79,18 +120,18 @@ ### Option: `tsconfig` | ||
Specifies how to resolve TypeScript options: | ||
- `true` (default) loads your project's `tsconfig.json` file. | ||
- `true` (the default) will load your project's `tsconfig.json` file. | ||
- _Note: The file is assumed to live in the current working directory._ | ||
- `false` or `''` (empty string) will use an empty tsconfig, causing the selected transpiler to use its own default settings. | ||
- a non-empty string is assumed to be the path to the tsconfig file to use (e.g., `'./tsconfig.prod.json'`), or the name of an installed npm package exposing a tsconfig file (e.g., `'@tsconfig/node16/tsconfig.json'`). | ||
- an object is assumed to be a [`TsConfigJson`](https://github.com/sindresorhus/type-fest/blob/main/source/tsconfig-json.d.ts) object. | ||
- a non-empty string is assumed to be the path to the `tsconfig.json` file to load (e.g., `'./tsconfig.prod.json'`) or the name of an installed npm package exposing a `tsconfig.json` file (e.g., `'@tsconfig/node16/tsconfig.json'`). | ||
- an object is assumed to be a [`TsConfigJson`](https://www.typescriptlang.org/tsconfig/) object (note: the `TsConfigJson` interface is re-exported from [type-fest](https://github.com/sindresorhus/type-fest?tab=readme-ov-file#miscellaneous)). | ||
- `false` or an empty string will cause the selected transpiler to use its own default settings. | ||
- finally, if this parameter is a function, it must return any of the above, or a promise to a any of the above. | ||
## Things you should know | ||
- The plugin aims to emit the same code TypeScript's `tsc` would have given the passed tsconfig, no more, no less. Therefore, none of the supported transpilers specificities/unique features are exposed. In the simplest case, the transpiler is just a *"get rid of type annotations"* tool -- and a very fast one, for that matter.<br /> | ||
To achieve its goal, the plugin does its best to call the selected transpiler's `transform` API with settings derived from the passed `tsconfig.json`. For example, TypeScript's `target` setting is mapped to the transpiler's corresponding setting.<br /> | ||
There are a few cases where this mapping is not 100% accurate. To continue with the `target` example, TypeScript defaults to `ES3` if the setting is not specified. This is fine with `swc` and `sucrase`, but not with `esbuild`, who supports ES5+ only. In such cases, a warning is emitted and the nearest setting is selected instead. | ||
- Because Rollup internally works with ESM source files, the transpiler's output is always set to `'esm'`. Still, CommonJS features like `require()`, `__filename` and `__dirname` are left untouched, so you will want to ensure that either `output.format` is set to `'cjs'` in `rollup.config.js`, or that appropriate shims are used. | ||
- Likewise, dynamics imports are always left untouched. | ||
- The plugin aims to emit the same code TypeScript's `tsc` would have given the passed `tsconfig.json`, no more, no less. Therefore, none of the supported transpilers specificities/unique features are exposed. In the simplest case, the transpiler is just a *"get rid of type annotations"* tool -- and a very fast one, for that matter.<br> | ||
To achieve its goal, the plugin does its best to call the selected transpiler's `transform` API with settings derived from the passed `tsconfig.json`. For example, TypeScript's `target` setting is mapped to the transpiler's corresponding setting.<br> | ||
- Because Rollup internally works with ESM source files, the transpiler's output is always set to `'esm'`. | ||
- `swc` does not handle [Typescript's import assignments](https://www.typescriptlang.org/docs/handbook/modules/reference.html#export--and-import--require) when targetting esm and will error out when it encounters one. | ||
## About warnings | ||
## Generated warnings | ||
The plugin may issue a few warnings during the build phase; here are their meaning. | ||
@@ -101,20 +142,7 @@ | ||
To mitigate this, you should [set the `isolatedModules` option to true in tsconfig](https://www.typescriptlang.org/tsconfig#isolatedModules) and let your IDE warn you when such incompatible constructs are used. | ||
To mitigate this, you should [set the `isolatedModules` option to true in tsconfig](https://www.typescriptlang.org/tsconfig#isolatedModules) and let your editor warn you when such incompatible constructs are used. | ||
You should also run `tsc --noEmit` sometime in your build steps to double check. | ||
### (other warnings: TODO) | ||
## Considerations | ||
Why let Rollup do the tree-shaking and bundling?, you may ask. | ||
IMHO, Rollup is still the best at tree-shaking and bundling. It offers the more control on what can be done and, when configured properly, emits the best code possible with very little if no bloat. | ||
So the choice here is to trade some speed in the bundling phase in exchange for power and precision. I believe this is a reasonable choice. | ||
Also, if you want to have `esbuild` do the bundling... Why use Rollup in the first place? | ||
## License | ||
MIT |
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
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
0
142
0
25178
6
7
392
+ Addedtype-fest@^0.13.1
+ Addedtype-fest@0.13.1(transitive)