Existing programs
1. awesome-typescript-loader
- This NPM package has not been updated for a long time and is not recommended because there are omissions in type checking
2. ts-loader + babel-loader + fork-ts-checker-webpack-plugin
- In this scenario, ts-Loader calls typescript when Webpack compiles (so local projects need typescript installed), and typescript runs to read the local tsconfig.json file.
- By default, ts-Loader performs translation and type checking. Whenever a file is changed, the translation and type checking will be repeated. If there are too many files, it will be very slow, affecting the development speed. Fork-ts-checker-webpack-plugin is used to create a separate thread to perform type checking without affecting the speed of webpack recompilation.
- Fork-ts-checker-webpack-plugin This plugin requires a minimum of Node.js 6.11.5, webpack 4, TypeScript 2.1, and optional ESLint 6 (which itself requires a minimum of Node.js 8.10.0).
Webpack configuration method 1
- With the parallelization of build speed (Thread-loader), the speed increase for WebPack 4+ may not be obvious
webpack.config.js
const cpus = require('os').cpus().length;
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
module.exports = {
module: {
rules: [
/ / a single process
/ / {
// test: /\.tsx? $/,
// By default, ts-loader does translation and type checking
// Since it is a single process, WebPack can collect error information and send it back to the browser via dev-server
// But this also leads to a very slow WebPack build
// use:['ts-loader']
/ /},
/ / process
{
test: /\.tsx? $/.
exclude: /node_modules/.
use: [
{loader: 'cache-loader'},
{
loader: 'thread-loader'.
options: {
workers: cpus - 1.
},
},
'babel-loader'.
{
loader: 'ts-loader'.
options: {
// Turn off type checking, that is, only translation
// Type checking is done by fork-ts-checker-webpack-plugin in another thread
// transpileOnly: true,
// If happyPackMode is set to true
TranspileOnly: true is implicitly set
happyPackMode: true
// If it is a VUE application, you need to configure this
// appendTsSuffixTo: [/\.vue$/]
}
}
]
},
{
test: /\.(js|jsx)$/.
use: ['happypack/loader? id=js'].
exclude: [/node_modules/, /(.|_)min\.js$/],
// include: [
// path.resolve(__dirname, "src")
/ /,
}
].
},
plugins: [
// fork a process to check
new ForkTsCheckerWebpackPlugin({
// Async is false and synchronously reports an error to Webpack. If an error is reported, webPack will fail to compile
// Async defaults to true and asynchronously reports error information to Webpack. If an error is reported, webPack compilation will not be affected
// async: false,
// eslint: false,
checkSyntacticErrors: true
})
]
};
Copy the code
tsconfig.json
{
"compilerOptions": {
//"module": "commonjs".
"target": "es5".
/* In 'react' mode, ts will compile TSX to JSX and JSX to js*/
/* In 'Preserve' mode, TS will compile TSX to JSX, instead of JSX to JS, leaving JSX */
/* To retain JSX, configure babel-loader in front of ts-loader to handle JSX */
/* In other words: set this value */ only if you want to use babel-laoder
"jsx": "preserve".
},
}
Copy the code
Webpack configuration method 2
- Compile TS/TSX files without parallel builds (Thread-loader)
const cpus = require('os').cpus().length;
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
module.exports = {
module: {
rules: [
{
test: /\.tsx? $/.
exclude: /node_modules/.
use: [
'babel-loader'.
{
loader: 'ts-loader'.
options: {
// Turn off type checking, that is, only translation
// Type checking is done by fork-ts-checker-webpack-plugin in another thread
transpileOnly: true.
}
}
]
},
{
test: /\.(js|jsx)$/.
use: ['happypack/loader? id=js'].
exclude: [/node_modules/, /(.|_)min\.js$/],
// include: [
// path.resolve(__dirname, "src")
/ /,
}
].
},
plugins: [
// fork a process to check
new ForkTsCheckerWebpackPlugin({
// Async is false and synchronously reports an error to Webpack. If an error is reported, webPack will fail to compile
// Async defaults to true and asynchronously reports error information to Webpack. If an error is reported, webPack compilation will not be affected
// async: false,
// eslint: false,
checkSyntacticErrors: true
})
]
};
Copy the code
tsconfig.json
{
"compilerOptions": {
//"module": "commonjs".
"target": "es5".
/* In 'react' mode, ts will compile TSX to JSX and JSX to js*/
/* In 'Preserve' mode, TS will compile TSX to JSX, instead of JSX to JS, leaving JSX */
/* To retain JSX, configure babel-loader in front of ts-loader to handle JSX */
/* In other words: set this value */ only if you want to use babel-laoder
"jsx": "preserve".
},
}
Copy the code
3. babel-loader + @babel/preset-typescript
- In this scenario, when Webpack compiles, babel-loader reads the configuration in.babelrc, doesn’t call typescript (so local projects don’t need to install typescript), and doesn’t check for types
- Tsconfig. json needs to be configured, however, because idea needs to be prompted with error messages during code development
webpack.config,js
rules: [
{
test:/\.(tsx? |jsx?) $/.
// @babel/core is called by default
use:'babel-loader'
}
]
Copy the code
.babelrc
{
"presets": [
"@babel/preset-env"
"@babel/preset-react".
"@babel/preset-typescript"
]
}
Copy the code
Q&A
The main differences between awesome-typescript-loader and TS-loader
- Awesome-typescript-loader does not require additional plug-ins to be installed and type checking can be performed in a separate process via the built-in CheckerPlugin
- Compile time comparison:
- Awesome -typescript-loader is faster if you use the default configuration
- If type checking is disabled, ts-Loader is relatively fast
- Awesome -typescript-loader is faster if type checking is disabled and executed in a separate process
Parallel builds are no longer appropriate for new versions of WebPack
It’s possible to parallelise your builds. Historically this was useful from a performance perspective with webpack 2 / 3. With webpack 4+ there appears to be significantly less benefit and perhaps even cost.
But if that’s what you want to do, there’s two ways to achieve this: happypack and thread-loader. Both should be used in combination with fork-ts-checker-webpack-plugin for typechecking.)
- There are two ways to parallelize builds: happypack and Thread-loader
- Parallel builds provide a significant performance boost for WebPack 2/3, and with WebPack 4+ the speed gain seems to be much less.
Why Babel when you use TypeScript
- Most of the existing projects rely on Babel
- Some requirements/functions need to be implemented by Babel plug-ins (e.g., load on demand)
- Babel has a very rich set of plugins, and its ecosystem is thriving
- Before Babel 7: The first two schemes are needed to translate TS
- After Babel 7: Babel directly removes TS and converts to JS, which makes it fast to compile
Why use babel-loader after ts-loader
- Ts-loader will not read the configuration in. Babelrc, that is, can not use the Babel series plug-in, so directly use TS-loader to convert TS/TSX to JS, there will be problems that gaskets cannot be loaded on demand, antD cannot be imported on demand. Therefore, we need to use TS-loader to convert TS/TSX into JS/JSX, and then use babel-loader to call Babel series plug-ins to compile into the final JS.
How to choose a translation scheme
- To use TS in older projects, consider using the TS-loader + fork-ts-checker-webpack-plugin. Consider using @babel/preset-typescript for new projects. The former option has type checking by default.
What if I also want type checking when using babel-loader + @babel/preset-typescript
package.json
{
"scripts": {
// open another NPM script to automatically check the type
"type-check": "tsc --watch".
},
"devDependencies": {
"@babel/cli": "^ 7.4.4." ".
"@babel/core": "^ 7.4.5".
"@babel/plugin-proposal-class-properties": "^ 7.4.4." ".
"@babel/plugin-proposal-object-rest-spread": "^ 7.4.4." ".
"@babel/preset-env": "^ 7.4.5".
"@babel/preset-typescript": "^ 7.3.3." ".
"typescript": "^ 3.5.2." "
}
}
Copy the code
tsconfig.json
{
"compilerOptions": {
// Do no file generation, only type checking
"noEmit": true.
},
}
Copy the code
Cautions for using @babel/preset-typescript
There are four syntax types that cannot be compiled in Babel
- Namespace: Don’t use it anymore. It’s outdated. Switch to the standard ES6 Module (
import
/export
),Recommended TSLint rulesYou are also advised not to use Namesapce.
namespace Person{
const name = 'abc';
}
Copy the code
- Type assertion: Use as to assert types.
interface Person {
name: string;
age: number
}
let p1 = {age: 18} as Person;
console.log(p2.name);
let p2 = <Person>{age: 18};
console.log(p3.name);
Copy the code
- Constant enumeration
const enum Sex {
man,
woman
}
Copy the code
- Legacy import/export syntax:
The import XXX = the require (...).
和export = xxx
.
Why Typescript officially switched to ESLint
- There are architectural issues with the way TSLint executes rules that affect performance, and fixing these issues would break existing rules;
- ESLint has better performance and more users
Why ESLint when you use TypeScript
- TS is mainly used for type checking and language conversions, with a little syntax checking
- ESLint is primarily used to check for code style and syntax errors
Use ‘NPX create-react-app XXX –typescript’ to quickly create TS projects
Configure Demo for the three schemes
- webpack-translate-typescript-demo
reference
TypeScript and Babel: A beautiful marriage
Replace awl-typescript-loader and TS-loader with @babel/preset-typescript
build-performance
https://segmentfault.com/q/1010000019545436
Recommended reading
Do you really understand the React lifecycle
React Hooks 【 nearly 1W words 】+ project combat
React SSR: + 2 projects
Implement a simple Webpack from 0 to 1
Cookie, Session, Token, JWT