React 与 webpack 教程
React 与 webpack 教程
本指南将教你如何将 TypeScript 与 React 及 webpack 结合使用,完成一个从零开始的项目搭建。
如果你正在启动一个全新的项目,可以先阅读 React 快速上手指南。
初始化项目结构
首先,创建一个新的项目目录。本教程将其命名为 proj,你可以根据需要改为其他名称。
text
mkdir proj
cd proj
我们将按以下结构组织项目:
text
proj/
├─ dist/
└─ src/
└─ components/
src目录用于存放 TypeScript 源码文件src/components目录用于存放自定义的 React 组件dist目录将由 webpack 自动生成,存放最终打包后的文件
创建基础目录结构:
text
mkdir src
cd src
mkdir components
cd ..
初始化 npm 工程
将当前目录初始化为一个 npm 包:
text
npm init -y
该命令将使用默认配置生成一个 package.json 文件。
安装依赖
安装 webpack
确保已全局安装 webpack,然后将其作为开发依赖安装到本地:
text
npm install --save-dev webpack webpack-cli
webpack 是一个模块打包工具,它可以将你的所有代码及其依赖打包成一个(或多个).js 文件。
安装 React 及其类型声明
安装 React 和 React-DOM 作为项目依赖,同时安装它们的 TypeScript 类型声明文件:
text
npm install --save react react-dom
npm install --save-dev @types/react @types/react-dom
@types/ 前缀表示我们额外获取 React 和 React-DOM 的声明文件。一般情况下,TypeScript 会从包自身的类型声明中查找类型;如果包未包含声明文件,TypeScript 则会去查找 @types/ 下的对应声明包。
安装 TypeScript 及 webpack 加载器
安装 TypeScript、ts-loader 和 source-map-loader 作为开发依赖:
text
npm install --save-dev typescript ts-loader source-map-loader
这些工具的作用如下:
- ts-loader:让 webpack 使用 TypeScript 的标准配置文件
tsconfig.json来编译 TypeScript 代码。 - source-map-loader:读取 TypeScript 生成的 sourcemap 文件,帮助 webpack 生成属于自己的 sourcemaps。这样,你在调试最终打包文件时,可以直接调试 TypeScript 源代码。
注意:
ts-loader不是唯一的 TypeScript 加载器,你也可以选择使用 awesome-typescript-loader。两者之间的区别可查看这里。
以上将 TypeScript 安装为开发依赖。虽然你也可以通过
npm link typescript链接到全局的 TypeScript 副本,但这不是常规做法。
添加 TypeScript 配置文件
我们需要创建一个 tsconfig.json 文件,用于指定 TypeScript 编译器需要处理的文件列表以及编译选项。
在项目根目录下新建 tsconfig.json 文件,并添加以下内容:
javascript
{
"compilerOptions": {
"outDir": "./dist/",
"sourceMap": true,
"noImplicitAny": true,
"module": "commonjs",
"target": "es6",
"jsx": "react"
}
}
各选项的简要说明:
outDir:编译输出的目录。sourceMap:生成.map文件,便于调试。noImplicitAny:禁止隐式any类型。module:指定模块代码生成方式,这里使用commonjs。target:指定编译后的 JavaScript 目标版本,这里使用 ES6。jsx:指定 JSX 代码的编译方式,react表示将 JSX 转换为 React.createElement 调用。
更多关于 tsconfig.json 的说明,可参考 tsconfig.json 文档。
编写代码
接下来,让我们用 React 编写一段 TypeScript 代码。
创建 Hello 组件
在 src/components 目录下创建一个名为 Hello.tsx 的文件。
以下是使用函数组件的写法:
typescript
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>
);
也可以使用类组件的写法:
typescript
import * as React from 'react';
export interface HelloProps {
compiler: string;
framework: string;
}
// 'HelloProps' 描述了 props 的结构。
// 由于不涉及 state,因此使用 '{}' 类型。
export class Hello extends React.Component<HelloProps, {}> {
render() {
return (
<h1>
Hello from {this.props.compiler} and {this.props.framework}!
</h1>
);
}
}
创建入口文件
接下来,在 src 目录下创建 index.tsx 文件:
typescript
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')
);
注意,导入 Hello 组件时使用的是相对于当前文件的路径 ./components/Hello,而不是模块名。这一点很重要,否则 TypeScript 只会尝试在 node_modules 文件夹中查找。
创建 HTML 页面
在项目根目录 proj 下创建一个 index.html 文件,用于在浏览器中展示我们的组件:
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/main.js"></script>
</body>
</html>
这里直接引用了
node_modules中的 React 文件,方便快捷。你也可以将这些文件拷贝到其他目录,或者使用 CDN 上的 React 版本。Facebook 官方提供了一系列可用于生产环境的 React 文件,可参考这里。
创建 webpack 配置文件
在项目根目录下创建一个 webpack.config.js 文件:
javascript
module.exports = {
mode: 'production',
// Enable sourcemaps for debugging webpack's output.
devtool: 'source-map',
resolve: {
// Add '.ts' and '.tsx' as resolvable extensions.
extensions: ['.ts', '.tsx'],
},
module: {
rules: [
{
test: /\.ts(x?)$/,
exclude: /node_modules/,
use: [
{
loader: 'ts-loader',
},
],
},
// All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
{
enforce: 'pre',
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',
},
};
如果你对 externals 字段感到疑惑,这里做一下额外说明:
我们不想把 React 的所有代码打包进最终的文件中。这样做有两个好处:
- 减少编译时间。
- 浏览器可以缓存这些不常变化的第三方库,从而提升页面加载速度。
理想情况下,我们希望在浏览器中直接通过模块的方式引入 React,但大多数浏览器尚未原生支持模块系统。因此,大多数库(如 jQuery、_ 等)会将自身挂载到一个全局变量上,这种模式被称为“命名空间”模式。webpack 允许我们通过 externals 配置来兼容这种模式。
例如,通过配置 "react": "React",webpack 会将代码中对 "react" 的导入自动转换为从全局变量 React 中加载。
关于 webpack 配置的更多资料,可参考 webpack 官方文档。
构建并运行
在项目根目录下执行以下命令:
text
npx webpack
构建完成后,在浏览器中打开 index.html,你将会看到页面显示:
text
Hello from TypeScript and React!
至此,你已经成功地将 TypeScript、React 和 webpack 整合在一起,并完成了一个可运行的示例项目。
帮助我们改进文档
发现翻译问题或内容错误?请告诉我们。
