-
Notifications
You must be signed in to change notification settings - Fork 795
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Stencil dependency free - Faster compiler startup times - Reduce overall download and install time - Simplify requiring typescript for the various platforms, such as deno, browser and node - Ensure the stencil compiler is always using the typescript version it's built with
- Loading branch information
1 parent
4b9f8ab
commit 1973032
Showing
25 changed files
with
331 additions
and
351 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
import fs from 'fs-extra'; | ||
import { Plugin } from 'rollup'; | ||
import { join } from 'path'; | ||
import { BuildOptions } from '../../utils/options'; | ||
import terser from 'terser'; | ||
|
||
export function typescriptSourcePlugin(opts: BuildOptions): Plugin { | ||
const tsPath = require.resolve('typescript'); | ||
return { | ||
name: 'typescriptSourcePlugin', | ||
resolveId(id) { | ||
if (id === 'typescript') { | ||
return tsPath; | ||
} | ||
return null; | ||
}, | ||
load(id) { | ||
if (id === tsPath) { | ||
return bundleTypeScriptSource(tsPath, opts); | ||
} | ||
return null; | ||
}, | ||
}; | ||
} | ||
|
||
async function bundleTypeScriptSource(tsPath: string, opts: BuildOptions) { | ||
const fileName = `typescript-${opts.typescriptVersion.replace(/\./g, '_')}-bundle-cache${opts.isProd ? '.min' : ''}.js`; | ||
const cacheFile = join(opts.buildDir, fileName); | ||
|
||
try { | ||
// check if we've already cached this bundle | ||
return await fs.readFile(cacheFile, 'utf8'); | ||
} catch (e) {} | ||
|
||
// get the source typescript.js file to modify | ||
let code = await fs.readFile(tsPath, 'utf8'); | ||
|
||
// remove the default ts.getDefaultLibFilePath because it uses some | ||
// node apis and we'll be replacing it withour own anyways and | ||
code = removeFromSource(code, `ts.getDefaultLibFilePath = getDefaultLibFilePath;`); | ||
|
||
// remove the CPUProfiler since it uses node apis | ||
code = removeFromSource(code, `enableCPUProfiler: enableCPUProfiler,`); | ||
code = removeFromSource(code, `disableCPUProfiler: disableCPUProfiler,`); | ||
|
||
// trim off the last part that sets module.exports and polyfills globalThis since | ||
// we don't want typescript to add itself to module.exports when in a node env | ||
const tsEnding = `})(ts || (ts = {}));`; | ||
if (!code.includes(tsEnding)) { | ||
throw new Error(`"${tsEnding}" not found`); | ||
} | ||
const lastEnding = code.lastIndexOf(tsEnding); | ||
code = code.substr(0, lastEnding + tsEnding.length); | ||
|
||
// there's a billion unnecessary "var ts;" for namespaces | ||
// but we'll be using the top level "const ts" instead | ||
code = code.replace(/var ts;/g, ''); | ||
|
||
// minification is crazy better if it doesn't use typescript's | ||
// namespace closures, like (function(ts) {...})(ts = ts || {}); | ||
code = code.replace(/ \|\| \(ts \= \{\}\)/g, ''); | ||
|
||
// make a nice clean default export | ||
// "process.browser" is used by typescript to know if it should use the node sys or not | ||
// this ensures its using our checks. Deno should also use process.browser = true | ||
// because we don't want deno using the node apis | ||
const o: string[] = []; | ||
o.push(`import { IS_NODE_ENV } from '@utils';`); | ||
o.push(`process.browser = !IS_NODE_ENV;`); | ||
o.push(`const ts = {};`); | ||
o.push(code); | ||
o.push(`export default ts;`); | ||
code = o.join('\n'); | ||
|
||
if (opts.isProd) { | ||
const minified = terser.minify(code, { | ||
ecma: 2018, | ||
module: true, | ||
compress: { | ||
ecma: 2018, | ||
passes: 2, | ||
}, | ||
output: { | ||
ecma: 2018, | ||
comments: false, | ||
}, | ||
}); | ||
|
||
if (minified.error) { | ||
throw minified.error; | ||
} | ||
code = minified.code; | ||
} | ||
|
||
await fs.writeFile(cacheFile, code); | ||
|
||
return code; | ||
} | ||
|
||
function removeFromSource(srcCode: string, removeCode: string) { | ||
if (!srcCode.includes(removeCode)) { | ||
throw new Error(`"${removeCode}" not found`); | ||
} | ||
return srcCode.replace(removeCode, `/* commented out: ${removeCode} */`); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.