讓我們新建一個(gè)目錄。
將會(huì)命名為proj,但是你可以改成任何你喜歡的名字。
mkdir proj
cd proj
我們會(huì)像下面的結(jié)構(gòu)組織我們的工程:
proj/
+- src/
| +- components/
|
+- dist/
TypeScript文件會(huì)放在src文件夾里,通過(guò)TypeScript編譯器編譯,然后經(jīng)webpack處理,最后生成一個(gè)bundle.js文件放在dist目錄下。
我們自定義的組件將會(huì)放在src/components文件夾下。
下面來(lái)創(chuàng)建基本結(jié)構(gòu):
mkdir src
cd src
mkdir components
cd ..
mkdir dist
現(xiàn)在把這個(gè)目錄變成npm包。
npm init
你會(huì)看到一些提示。
你可以使用默認(rèn)項(xiàng)除了開始腳本。
使用./dist/bundle.js做為開始腳本。
當(dāng)然,你也可以隨時(shí)到生成的package.json文件里修改。
首先確保TypeScript,typings和webpack已經(jīng)全局安裝了。
npm install -g typescript typings webpack
Webpack這個(gè)工具可以將你的所有代碼和可選擇地將依賴?yán)壋梢粋€(gè)單獨(dú)的.js文件。
Typings是一個(gè)包管理器,它是用來(lái)獲取定義文件的。
現(xiàn)在我們添加React和React-DOM依賴到package.json文件里:
npm install --save react react-dom
接下來(lái),我們要添加開發(fā)時(shí)依賴ts-loader和source-map-loader。
npm install --save-dev ts-loader source-map-loader
npm link typescript
這些依賴會(huì)讓TypeScript和webpack在一起良好地工作。
ts-loader可以讓webpack使用TypeScript的標(biāo)準(zhǔn)配置文件tsconfig.json編譯TypeScript代碼。
source-map-loader使用TypeScript輸出的sourcemap文件來(lái)告訴webpack何時(shí)生成自己的sourcemaps。
這就允許你在調(diào)試最終生成的文件時(shí)就好像在調(diào)試TypeScript源碼一樣。
鏈接TypeScript,允許ts-loader使用全局安裝的TypeScript,而不需要單獨(dú)的本地拷貝。
如果你想要一個(gè)本地的拷貝,執(zhí)行npm install typescript。
最后,我們使用typings工具來(lái)獲取React的聲明文件:
typings install --global --save "dt~react"
typings install --global --save "dt~react-dom"
--global標(biāo)記,還有dt~前綴,告訴Typings從DefinitelyTyped獲取聲明文件,它是一個(gè)由社區(qū)維護(hù)的.d.ts文件倉(cāng)庫(kù)。
這個(gè)命令會(huì)創(chuàng)建一個(gè)名為typings.json的文件和一個(gè)typings目錄在當(dāng)前目錄下。
下面使用React寫一段TypeScript代碼。
首先,在src/components目錄下創(chuàng)建一個(gè)名為Hello.tsx的文件,代碼如下:
import * as React from "react";
import * as ReactDOM from "react-dom";
export class HelloComponent extends React.Component<any, any> {
render() {
return <h1>Hello from {this.props.compiler} and {this.props.framework}!</h1>;
}
}
注意一點(diǎn)這個(gè)例子已經(jīng)很像類了,我們不再需要使用類。 使用React的其它方式(比如無(wú)狀態(tài)的功能組件)。
接下來(lái),在src下創(chuàng)建index.tsx文件,源碼如下:
import * as React from "react";
import * as ReactDOM from "react-dom";
import { HelloComponent } from "./components/Hello";
ReactDOM.render(
<HelloComponent compiler="TypeScript" framework="React" />,
document.getElementById("example")
);
我們僅僅將Hello組件導(dǎo)入index.tsx。
注意,不同于"react"或"react-dom",我們使用index.tsx的相對(duì)路徑 - 這很重要。
如果不這樣做,TypeScript只會(huì)嘗試在node_modules文件夾里查找。
其它使用React的方法也應(yīng)該可以。
我們還需要一個(gè)頁(yè)面來(lái)顯示Hello組件。
在根目錄proj創(chuàng)建一個(gè)名為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/dist/react.js"></script>
<script src="./node_modules/react-dom/dist/react-dom.js"></script>
<!-- Main -->
<script src="./dist/bundle.js"></script>
</body>
</html>
需要注意一點(diǎn)我們是從node_modules引入的文件。
React和React-DOM的npm包里包含了獨(dú)立的.js文件,你可以在頁(yè)面上引入它們,這里我們?yōu)榱丝旖菥椭苯右昧恕?可以隨意地將它們拷貝到其它目錄下,或者從CDN上引用。
Facebook在CND上提供了一系列可用的React版本,你可以在這里查看更多內(nèi)容。
現(xiàn)在,可以把所有TypeScript文件放在一起 - 包括我們編寫的代碼和必要的typings文件。
現(xiàn)在需要?jiǎng)?chuàng)建tsconfig.json文件,它包含輸入文件的列表和編譯選項(xiàng)。
在根目錄下執(zhí)行下在命令:
tsc --init ./typings/main.d.ts ./src/index.tsx --jsx react --outDir ./dist --sourceMap --noImplicitAny
你可以在這里學(xué)習(xí)到更多關(guān)于tsconfig.json。
新建一個(gè)webpack.config.js文件在工程根目錄下。
module.exports = {
entry: "./src/index.tsx",
output: {
filename: "./dist/bundle.js",
},
// Enable sourcemaps for debugging webpack's output.
devtool: "source-map",
resolve: {
// Add '.ts' and '.tsx' as resolvable extensions.
extensions: ["", ".webpack.js", ".web.js", ".ts", ".tsx", ".js"]
},
module: {
loaders: [
// All files with a '.ts' or '.tsx' extension will be handled by 'ts-loader'.
{ test: /\.tsx?$/, loader: "ts-loader" }
],
preLoaders: [
// All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
{ test: /\.js$/, loader: "source-map-loader" }
]
},
// When importing a module whose path matches one of the following, just
// assume a corresponding global variable exists and use that instead.
// This is important because it allows us to avoid bundling all of our
// dependencies, which allows browsers to cache those libraries between builds.
externals: {
"react": "React",
"react-dom": "ReactDOM"
},
};
大家可能對(duì)externals字段有所疑惑。
我們想要避免把所有的React都放到一個(gè)文件里,因?yàn)闀?huì)增加編譯時(shí)間并且瀏覽器還能夠緩存沒(méi)有發(fā)生改變的庫(kù)文件。
理想情況下,我們只需要在瀏覽器里引入React模塊,但是大部分瀏覽器還沒(méi)有支持模塊。
因此大部分代碼庫(kù)會(huì)把自己包裹在一個(gè)單獨(dú)的全局變量?jī)?nèi),比如:jQuery或_。
這叫做“命名空間”模式,webpack也允許我們繼續(xù)使用通過(guò)這種方式寫的代碼庫(kù)。
通過(guò)我們的設(shè)置"react": "React",webpack會(huì)神奇地將所有對(duì)"react"的導(dǎo)入轉(zhuǎn)換成從React全局變量中加載。
你可以在這里了解更多如何配置webpack。
執(zhí)行:
webpack
在瀏覽器里打開index.html,工程應(yīng)該已經(jīng)可以用了!
你可以看到頁(yè)面上顯示著“Hello from TypeScript and React!”