今天開始來探討如何使用 TS 結合 React 進行開發,要開發一個專案,最重要的就是建置開發環境。這裡我們會介紹兩種React + TypeScript 建置環境的方式,第一種是使用 create-react-app ,另一種是使用 Webpack 自建開發環境。如果想了解純 TS開發環境建置可以參考 Day02的文章。
npx create-react-app my-project --typescript
一行指令很迅速地就把開發環境建好了!資料夾結構如下:
備註:如果之前曾使用
npm install -g create-react-app
全域安裝 create-react-app ,建議先卸除安裝npm uninstall -g create-react-app
以確保 npx 是最新的版本。
若原本使用 create-react-app 建置專案,想要切換成 TS 進行開發,則可以進行下面步驟:
npm install --save typescript @types/node @types/react @types/react-dom @types/jest
這時候,所有檔案仍然維持是原本 JS 版本
接下來,將.js結尾檔名手動改成.tsx,再重新啟動開發伺服器。這時候,所有的型別錯誤都會顯示在開發面板的終端機上,需要修復所有型別錯誤,才能繼續開發。
倘若是原本使用 TS 進行開發,想要回到原本 JS 寫法,也可以參考此部落格文章
資料來源: create-react-app官網說明
npm init -y
這時候會創建一個package.json檔案
npm install --save-dev webpack webpack-cli
npm install --save react react-dom
npm install --save-dev @types/react @types/react-dom
Webpack 工具可以將所有程式碼壓縮成一個JS檔案。@type 前綴字表示要額外獲取 React 和 React-DOM 的聲明文件,通常當 import "react" 路徑時,TS 會查看 react 資料夾; 但不是所有資料夾都有聲明文件,所以 TS 還會檢查 @types/react 資料夾。
npm install --save-dev typescript ts-loader source-map-loader
這些套件可以讓 TS 和 Webpack 很好的結合使用。ts-loader 幫助 webpack 使用 TS 標準設定文件 tsconfig.json 進行編譯,而 source-map-loader 可以幫助除錯。
什麼是 source map 呢? 簡單來說,source map 是儲存程式碼轉換前後對應的位置的檔案,由於 webpack 會將程式碼打包和壓縮,而透過 source map 可以在程式碼出錯時,方便我們找到錯誤的程式碼在哪一隻檔案。
使用 source-map-loader 在最後輸出文件 debug 時就像在原本的 TS 程式碼中 debug 一樣。
ts-loader 不是唯一可使用的 loader,awesome-typescript-loader 也可以達到類似效果。兩者差異說明在此
在 tsconfig.json 檔案中進行編譯設定,更多編譯設定請參考Day 03的文章
{
"compilerOptions": {
"outDir": "./dist/",
"sourceMap": true,
"noImplicitAny": true,
"module": "commonjs",
"target": "es6",
"jsx": "react"
}
}
來創建幾個檔案吧!首先在跟 node.js 資料夾同層創建 src 資料夾,之後在 src 資料夾下再創建一個資料夾名稱叫 components,裡面放所有的元件。而後在 components 資料夾下創建 Hello.tsx 檔案
首先,來創一個functional component:
import * as React from "react";
export interface HelloProps { compiler: string; framework: string; }
export const Hello = (props: HelloProps) => <h1>Hello from {props.compiler} and {props.framework}!</h1>;
上面的程式碼也可以改成class component
import * as React from "react";
export interface HelloProps { compiler: string; framework: string; }
export class Hello extends React.Component<HelloProps, {}> {
render() {
return <h1>Hello from {this.props.compiler} and {this.props.framework}!</h1>;
}
}
HelloProps 定義了 props 的資料型別,而因為沒有 State,所以使用 {} 型別
接著在 src 下再創建一個 index.tsx 檔案如下:
import * as React from "react";
import * as ReactDOM from "react-dom";
import { Hello } from "./components/Hello";
ReactDOM.render(
<Hello compiler="TypeScript" framework="React" />,
document.getElementById("example")
);
這邊要注意的是,ReactDom.render 中要設定編譯器 TypeScript 和 framework React。
另外,我們還需要一個 html 檔來顯示 Hello 元件,在專案根目錄創建一個 index.html 檔案
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello React!</title>
</head>
<body>
<div id="example"></div>
<!-- Dependencies -->
<script src="./node_modules/react/umd/react.development.js"></script>
<script src="./node_modules/react-dom/umd/react-dom.development.js"></script>
<!-- Main -->
<script src="./dist/bundle.js"></script>
</body>
</html>
在根目錄下創建 webpack.config.js 檔案
module.exports = {
entry: "./src/index.tsx",
output: {
filename: "bundle.js",
path: __dirname + "/dist"
},
// 幫助webpack輸出檔案debug
devtool: "source-map",
resolve: {
// 加入'.ts' and '.tsx' 結尾
extensions: [".ts", ".tsx", ".js", ".json"]
},
module: {
rules: [
// 所有有.ts和.tsx結尾的檔案都可以被awesome-typescript-loader處理
{ test: /\.tsx?$/, loader: "awesome-typescript-loader" },
// 所有結尾為.js檔案會被source-map-loader處理
{ enforce: "pre", test: /\.js$/, loader: "source-map-loader" }
]
},
externals: {
"react": "React",
"react-dom": "ReactDOM"
}
};
最後面的 externals 主要用來避免將所有的 React 都打包放到同一個資料夾下,因為這會增加編譯時間,更多說明請參考webpack官網
執行
webpack
在瀏覽器打開index.html就可以看到 Hello from TypeScript and React!囉
參考資料:typescript官網