回顾
上一阶段,搭建了的是一个适配了普通的 js 代码的基础 webpack 框架:我是这样搭建React+TS的通用webpack脚手架的(阶段一)。但是,还存在几个主要问题:没有装载任何 ui 框架;没有搭配 Typescript 来使用;...
那么今天,就进入阶段二,把 React 和 Typescript 放入这个脚手架中,满足业务需求。
正文
搭配 Typescript
初始化
首先,在我们的项目中安装依赖:
yarn add --dev typescript
然后,在项目中使用 tsc --init 命令,在根目录下生成 tsconfig 文件。
这里我手动搜索了一个通用的 React 的 tsconfig 模板:
{
"compilerOptions": {
"outDir": "./dist/",
"sourceMap": true,
"noImplicitAny": true,
"module": "es6",
"target": "es5",
"jsx": "react",
"allowJs": true,
"moduleResolution": "node",
"allowSyntheticDefaultImports": true
},
"exclude": [
"node_modules",
"dist"
],
"types": [
"typePatches"
]
}
接下来,把我们目录下的 js 文件全部修改为 ts。
出现报错?
此时,在我们的 index.ts 文件中,由于引入了 ts,导致出现了报错:
根据提示,应该是少了对应 types 说明。在搜索资料后查询到,需要放入对应的 png、svg、jpg 等文件的声明文件才行。下面以 png 的声明文件为例:
在 src 目录下创建一个名为 import-png.d.ts 文件,内容:
declare module '*.png' {
const content: any;
export default content;
}
同时,顺便也加入 svg、gif 等文件的声明文件,只需要以上面内容为模板即可。
此时,再次打开我们的 index.ts,就可以看到,红线的报错已经被解决啦!
引入 ts-loader
由于使用了 ts ,那么 webpack 在打包的时候,就多了一个步骤,需要先把 ts 转为 js 代码,那这里就需要引入 ts-loader 来帮助做这个事情。
// webpack.base.config.js
module.exports = {
//...
module: {
rules: [{
test: /.(ts|tsx)$/, // 因为之后要适配 react,所以这里提前写入 tsx
use: [
{
loader: 'thread-loader',
options: {
}
},
'babel-loader',
{
loader: 'ts-loader',
options: {
happyPackMode: true,
transpileOnly: true
}
}
],
exclude: /node_modules/,
},
//...
]
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
}
配置 React
添加完 ts 相关的基本配置后,我们来开始配置 React 相关依赖。
安装依赖:
yarn add react react-dom
yarn add --dev @types/react @types/react-dom
修改相关文件
把我们的 index.ts 文件修改为 index.tsx ,修改内容为 React 一般的模板内容:
import React from 'react';
import ReactDOM from 'react-dom';
import Apps from './Apps';
const rootId = 'root';
const rootElement = document.getElementById(rootId);
if (!rootElement) {
throw new Error(`Unable to find element with id '${rootId}'`);
}
ReactDOM.render(
<Apps />,
rootElement
);
创建 Apps.tsx
import React from 'react';
import imageUrl from '../public/assets/a.png'
const Apps = (): React.ReactElement => {
return (
<div>
<p>Apps content</p>
<img src={imageUrl} alt=""/>
</div>
)
}
export default Apps;
修改 public/index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="root"></div>
<script src="js/test.js"></script>
</body>
</html>
此时使用 yarn start 运行项目,已经可以看到项目在浏览器上展示了!
这时候我们已经可以愉快的使用 react + typescript 协作进行开发啦!
babel 支持 react 和懒加载
安装依赖
yarn add --dev @babel/plugin-syntax-dynamic-import @babel/preset-react
打开 .babelrc 文件
{
"presets": [
["@babel/preset-env"],
["@babel/preset-react", {"targets": {"node": "current"}}]
],
"plugins": [
["@babel/plugin-transform-runtime", {"corejs": 3}],
["@babel/plugin-proposal-decorators", { "legacy": true }],
["@babel/plugin-proposal-class-properties", { "loose": true }],
["@babel/plugin-proposal-private-methods", { "loose": true }],
["@babel/plugin-syntax-dynamic-import"]
]
}
安装 tailwindcss (可选)
由于公司技术栈要求,这里还需要继续配置 tailwindcss 的相关配置
安装依赖:
yarn add --dev tailwindcss@latest @fullhuman/postcss-purgecss cssnano
这里我们是通过 postcss 与 tailwindcss 结合来进行使用,在根目录创建 postcss.config.js 文件
//postcss.config.js
const tailwindcss = require("tailwindcss");
const purgecss = require("@fullhuman/postcss-purgecss");
class TailwindExtractor {
static extract(content) {
return content.match(/[A-z0-9-:/]+/g);
}
}
module.exports = {
plugins: [
tailwindcss("./tailwind.config.js"),
require("autoprefixer"),
require("cssnano")({ preset: "default" }),
process.env.NODE_ENV === "production" &&
purgecss({
content: ["**/*.html", "./src/**/*.ts", "./src/*.ts", "./src/*.tsx", "./src/**/*.tsx"],
css: ["./src/**/*.css"],
extractors: [
{
extractor: new TailwindExtractor,
// Specify the file extensions to include when scanning
extensions: ["html", "ts", "tsx", "css"]
}
]
})
]
};
根据 tailwindcss 的官方文档,使用 npx tailwindcss init 命令,在根目录下创建一个 taiwindcss.config.js 文件
//taiwindcss.config.js
module.exports = {
purge: {
enabled: true,
content: [
'./public/*.html',
'./src/*.tsx',
'./src/**/*.tsx'
],
},
darkMode: false, // or 'media' or 'class'
theme: {
extend: {},
},
variants: {
extend: {},
},
plugins: [],
}
然后,需要在 src 目录下创建一个 css 文件夹,其中包含 styles.css 和 output.css 两个文件。output.css 也就是打包后生成的样式文件。
//styles.css
@tailwind base;
@tailwind components;
@tailwind utilities;
然后,为了让生成的样式生效,需要在 index.tsx 文件中对其进行引入
import './css/output.css'
//...
接下来,需要来配置项目的打包命令,这里使用 postcss-cli 和 concurrently 工具来配合使用
yarn add --dev postcss-cli concurrently
重新配置我们的 scripts 命令
{
...
"scripts": {
"start": "webpack serve --config build/webpack.dev.config.js --open",
"dev": "concurrently \"yarn watch:css \" \"yarn start \"",
"build": "yarn build:css && yarn build:prod",
"build:prod": "npx webpack --config build/webpack.prod.config.js",
"build:css": "postcss src/css/styles.css -o src/css/output.css",
"watch:css": "postcss src/css/styles.css -o src/css/output.css -w",
}
}
在开发环境下,最好使用 yarn dev 命令来进行开发,支持代码热替换和 tailwindcss 的热更新。正式打包则是使用 yarn build 命令来进行打包。
代码分析报告(可选)
使用 webpack-bundle-analyzer 插件来生成代码分析报告,帮助提升代码质量和网站性能。
安装依赖:
yarn add -dev webpack-bundle-analyzer
相关配置:
//webpack.dev.config.js
const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer");
module.exports = merge(baseConfig, {
//...
plugins: [
...baseConfig.plugins,
new BundleAnalyzerPlugin()
],
})
总结
到这里,也就完成了一个支持 React、Typescript、Taiwindcss 的一个通用的 webpack 脚手架,可以支持一般的项目来使用。源码链接:github.com/wbh13285517… 。