Skip to content

Commit 03f217a

Browse files
committed
feature #694 Add Encore.enableBabelTypeScriptPreset() to "compile" TypeScript with Babel (Kocal)
This PR was squashed before being merged into the master branch (closes #694). Discussion ---------- Add Encore.enableBabelTypeScriptPreset() to "compile" TypeScript with Babel See #691, I thought it can be interesting to have a test here. Using Babel to "compile" TypeScript is faster than using `ts-loader` or `tsc` directly, because in fact, it literally remove types annotations. To continue to check types, you have to run `tsc --emitDeclarationOnly` manually (or in a CI). But this is not part of the PR. To migrate an already existing TypeScript app, you just have to configure `babel-loader` to run over `.tsx?` file like this: ```diff Encore - .enableTypeScriptLoader() + .configureLoaderRule('javascript', loader => { + loader.test = /.(j|t)sx?$/; // let Babel to run over .tsx? files too + }) ``` Install some dependencies: `yarn add --dev @babel/preset-typescript @babel/plugin-proposal-class-properties`. And modify your Babel configuration: ```diff { "presets": [ "@babel/env", + "@babel/typescript" ], + "plugins": [ + "@babel/proposal-class-properties" + ] } ``` Maybe I can update `Encore.configureBabel()` and add an option to runs over TypeScript files too... like I did in #574, something like this: ```js Encore .configureBabel(null, { typescript: true }) ``` I've also changed the legacy import/export (`import a = require('...')` to `import a from '...'`). Because it's the legacy way (ES6 imports are very fine) and the Babel TypeScript was not compatible with them: ![Capture d’écran de 2020-02-07 22-06-11](https://user-images.githubusercontent.com/2103975/74066752-0a323100-49f8-11ea-91b8-cfdbc6de28a2.png) **EDIT :** Added `Encore.enableBabelTypeScriptPreset()` that do all the job for us! :) ```js // simple usage Encore.enableBabelTypeScriptPreset(); // configure TypeScript preset (https://babeljs.io/docs/en/babel-preset-typescript#options) Encore.enableBabelTypeScriptPreset({ isTSX: true; }) ``` `Encore.enableBabelTypeScriptPreset()` can not be used aside `Encore.enableTypeScriptLoader()` or `Encore.enableForkedTypeScriptTypesChecking()`. Commits ------- bdd553a chore: typo 96a666b feat: implement Encore.enableBabelTypeScriptPreset() 6f992b0 feat: prepare method "enableBabelTypeScriptPreset" 8238c32 fixture: add code that only works in TypeScript 66067a0 test: add test for TypeScript "compilation" with Babel 2e21d4f chore(deps-dev): install Babel TypeScript preset, with class properties plugin e053a5e fix(fixtures): use "better" syntax for TypeScript import/export
2 parents b09eb03 + bdd553a commit 03f217a

File tree

15 files changed

+384
-17
lines changed

15 files changed

+384
-17
lines changed

fixtures/js/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
import render = require('./render');
1+
import render from './render';
22

3-
render();
3+
render();

fixtures/js/render.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
function render() {
2-
document.getElementById('app').innerHTML = "<h1>Welcome to Your TypeScript App</h1>";
2+
const html: string = "<h1>Welcome to Your TypeScript App</h1>";
3+
document.getElementById('app').innerHTML = html;
34
}
45

5-
export = render;
6+
export default render;

fixtures/js/render2.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ function render() {
22
document.getElementById('app').innerHTML = "<h1>Welcome to Your TypeScript App</h1>";
33
}
44

5-
export = render;
5+
export default render;

fixtures/js/tsconfig.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
{
2-
"compilerOptions": {}
3-
}
2+
"compilerOptions": {
3+
"allowSyntheticDefaultImports": true
4+
}
5+
}

index.js

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -980,7 +980,7 @@ class Encore {
980980

981981
/**
982982
* If enabled, a Preact preset will be applied to
983-
* the generated Webpack configuration.
983+
* the generated Webpack and Babel configuration.
984984
*
985985
* ```
986986
* Encore.enablePreactPreset()
@@ -1044,6 +1044,42 @@ class Encore {
10441044
return this;
10451045
}
10461046

1047+
1048+
/**
1049+
* If enabled, a TypeScript preset will be applied to
1050+
* the generated Webpack and Babel configuration.
1051+
*
1052+
* ```
1053+
* Encore.enableBabelTypeScriptPreset()
1054+
* ```
1055+
*
1056+
* This method let Babel handle your TypeScript code
1057+
* and can not be used with `Encore.enableTypeScriptLoader()`
1058+
* or `Encore.enableForkedTypeScriptTypesChecking()`.
1059+
*
1060+
* Since all types are removed by Babel,
1061+
* you must run `tsc --noEmit` yourself for types checking.
1062+
*
1063+
* The Babel TypeScript preset can be configured,
1064+
* see https://babeljs.io/docs/en/babel-preset-typescript#options
1065+
* for available options.
1066+
*
1067+
* For example:
1068+
* ```
1069+
* Encore.enableBabelTypeScriptPreset({
1070+
* isTSX: true
1071+
* })
1072+
* ```
1073+
*
1074+
* @param {object} options
1075+
* @returns {Encore}
1076+
*/
1077+
enableBabelTypeScriptPreset(options) {
1078+
webpackConfig.enableBabelTypeScriptPreset(options);
1079+
1080+
return this;
1081+
}
1082+
10471083
/**
10481084
* If enabled, the Vue.js loader is enabled.
10491085
*

lib/WebpackConfig.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ class WebpackConfig {
109109
this.useEslintLoader = false;
110110
this.useTypeScriptLoader = false;
111111
this.useForkedTypeScriptTypeChecking = false;
112+
this.useBabelTypeScriptPreset = false;
112113
this.useWebpackNotifier = false;
113114
this.useHandlebarsLoader = false;
114115

@@ -130,6 +131,7 @@ class WebpackConfig {
130131
useBuiltIns: false,
131132
corejs: null,
132133
};
134+
this.babelTypeScriptPresetOptions = {};
133135
this.vueOptions = {
134136
useJsx: false,
135137
};
@@ -647,6 +649,10 @@ class WebpackConfig {
647649
}
648650

649651
enableTypeScriptLoader(callback = () => {}) {
652+
if (this.useBabelTypeScriptPreset) {
653+
throw new Error('Encore.enableTypeScriptLoader() can not be called when Encore.enableBabelTypeScriptPreset() has been called.');
654+
}
655+
650656
this.useTypeScriptLoader = true;
651657

652658
if (typeof callback !== 'function') {
@@ -657,6 +663,9 @@ class WebpackConfig {
657663
}
658664

659665
enableForkedTypeScriptTypesChecking(forkedTypeScriptTypesCheckOptionsCallback = () => {}) {
666+
if (this.useBabelTypeScriptPreset) {
667+
throw new Error('Encore.enableForkedTypeScriptTypesChecking() can not be called when Encore.enableBabelTypeScriptPreset() has been called.');
668+
}
660669

661670
if (typeof forkedTypeScriptTypesCheckOptionsCallback !== 'function') {
662671
throw new Error('Argument 1 to enableForkedTypeScriptTypesChecking() must be a callback function.');
@@ -667,6 +676,19 @@ class WebpackConfig {
667676
forkedTypeScriptTypesCheckOptionsCallback;
668677
}
669678

679+
enableBabelTypeScriptPreset(options = {}) {
680+
if (this.useTypeScriptLoader) {
681+
throw new Error('Encore.enableBabelTypeScriptPreset() can not be called when Encore.enableTypeScriptLoader() has been called.');
682+
}
683+
684+
if (this.useForkedTypeScriptTypeChecking) {
685+
throw new Error('Encore.enableBabelTypeScriptPreset() can not be called when Encore.enableForkedTypeScriptTypesChecking() has been called.');
686+
}
687+
688+
this.useBabelTypeScriptPreset = true;
689+
this.babelTypeScriptPresetOptions = options;
690+
}
691+
670692
enableVueLoader(vueLoaderOptionsCallback = () => {}, vueOptions = {}) {
671693
this.useVueLoader = true;
672694

lib/config-generator.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -250,8 +250,7 @@ class ConfigGenerator {
250250

251251
let rules = [
252252
applyRuleConfigurationCallback('javascript', {
253-
// match .js and .jsx
254-
test: /\.jsx?$/,
253+
test: babelLoaderUtil.getTest(this.webpackConfig),
255254
exclude: this.webpackConfig.babelOptions.exclude,
256255
use: babelLoaderUtil.getLoaders(this.webpackConfig)
257256
}),

lib/features.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,15 @@ const features = {
7878
],
7979
description: 'check TypeScript types in a separate process'
8080
},
81+
'typescript-babel': {
82+
method: 'enableBabelTypeScriptPreset',
83+
packages: [
84+
{ name: 'typescript' },
85+
{ name: '@babel/preset-typescript', enforce_version: true },
86+
{ name: '@babel/plugin-proposal-class-properties', enforce_version: true },
87+
],
88+
description: 'process TypeScript files with Babel'
89+
},
8190
vue: {
8291
method: 'enableVueLoader()',
8392
// vue is needed so the end-user can do things

lib/loaders/babel.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,13 @@ module.exports = {
5858
plugins: ['@babel/plugin-syntax-dynamic-import']
5959
});
6060

61+
if (webpackConfig.useBabelTypeScriptPreset) {
62+
loaderFeatures.ensurePackagesExistAndAreCorrectVersion('typescript-babel');
63+
64+
babelConfig.presets.push(['@babel/preset-typescript', webpackConfig.babelTypeScriptPresetOptions]);
65+
babelConfig.plugins.push('@babel/plugin-proposal-class-properties');
66+
}
67+
6168
if (webpackConfig.useReact) {
6269
loaderFeatures.ensurePackagesExistAndAreCorrectVersion('react');
6370

@@ -95,5 +102,21 @@ module.exports = {
95102
options: babelConfig
96103
}
97104
];
105+
},
106+
107+
/**
108+
* @param {WebpackConfig} webpackConfig
109+
* @return {RegExp} to use for eslint-loader `test` rule
110+
*/
111+
getTest(webpackConfig) {
112+
const extensions = [
113+
'jsx?', // match .js and .jsx
114+
];
115+
116+
if (webpackConfig.useBabelTypeScriptPreset) {
117+
extensions.push('tsx?'); // match .ts and .tsx
118+
}
119+
120+
return new RegExp(`\\.(${extensions.join('|')})$`);
98121
}
99122
};

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@
5555
},
5656
"devDependencies": {
5757
"@babel/plugin-transform-react-jsx": "^7.0.0",
58+
"@babel/plugin-proposal-class-properties": "^7.0.0",
5859
"@babel/preset-react": "^7.0.0",
60+
"@babel/preset-typescript": "^7.0.0",
5961
"@vue/babel-helper-vue-jsx-merge-props": "^1.0.0-beta.3",
6062
"@vue/babel-preset-jsx": "^1.0.0-beta.3",
6163
"autoprefixer": "^8.5.0",

0 commit comments

Comments
 (0)