我是这样搭建React+TS的通用webpack脚手架的(阶段二)

1,593 阅读4分钟

回顾

上一阶段,搭建了的是一个适配了普通的 js 代码的基础 webpack 框架:我是这样搭建React+TS的通用webpack脚手架的(阶段一)。但是,还存在几个主要问题:没有装载任何 ui 框架;没有搭配 Typescript 来使用;...

那么今天,就进入阶段二,把 React 和 Typescript 放入这个脚手架中,满足业务需求。

正文

搭配 Typescript

初始化

首先,在我们的项目中安装依赖:

yarn add --dev typescript

然后,在项目中使用 tsc --init 命令,在根目录下生成 tsconfig 文件。 这里我手动搜索了一个通用的 Reacttsconfig 模板:

{
  "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,导致出现了报错: image.png

根据提示,应该是少了对应 types 说明。在搜索资料后查询到,需要放入对应的 pngsvgjpg 等文件的声明文件才行。下面以 png 的声明文件为例:

在 src 目录下创建一个名为 import-png.d.ts 文件,内容:

declare module '*.png' {
  const content: any;

  export default content;
}

同时,顺便也加入 svggif 等文件的声明文件,只需要以上面内容为模板即可。

此时,再次打开我们的 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

这里我们是通过 postcsstailwindcss 结合来进行使用,在根目录创建 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.cssoutput.css 两个文件。output.css 也就是打包后生成的样式文件。

//styles.css
@tailwind base;
@tailwind components;
@tailwind utilities;

然后,为了让生成的样式生效,需要在 index.tsx 文件中对其进行引入

import './css/output.css'

//...

接下来,需要来配置项目的打包命令,这里使用 postcss-cliconcurrently 工具来配合使用

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…