likes
comments
collection
share

基于 Vite 从 0 到 1 启动一个 React 项目

作者站长头像
站长
· 阅读数 11

如果不使用 Vite 官方提供的 template 选项,要如何从一个 Vite 依赖的情况下逐步配置启动一个 React?如何实现 Webpack 的静态资源服务,如何实现基于 WebpackloaderJSX 的自动转换

下面是这个项目运行效果,以及完整的示例源代码

基于 Vite 从 0 到 1 启动一个 React 项目

普通启动

如果你是刚开始接触 HTML/CSS/JavaScript 三件套开始接触的前端,那么你可能比较熟悉或者比较能接受的引入 React 的方式可能是使用 CDN 的方式,大概如下(下面这个是我要介绍的例子)

<head>
  <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
</head>
<body>
  <div id="root"></div>
</body>
<script>
  const useState = React.useState;
  const createElement = React.createElement;

  function App() {
    const [count, setCount] = useState(0);

    const handleClick = () => {
     setCount((count) => count + 1);
    };

    return createElement("div", {
      children: [
        "count:" + count,
        createElement(
          "button",
          {
            key: "2",
            onClick: handleClick,
          },
          "click + 1"
        ),
      ],
    });
  }

  const root = ReactDOM.createRoot(document.getElementById("root"));
  root.render(
    createElement(React.StrictMode, {
      children: [createElement(App, { key: "1" })],
    })
  );
</script>

但这种方式是基于 React.createElement 去编写 DOM 的代码的,React 中比较常用的是 JSX 语法,它们的文档认为 JSX

它有助于编写UI代码 - 无论是使用 React 还是其他库。

React 的文档推荐使用 JSX 的方式是使用 babel 转换,其实使用 babel 这已经涉及到前端工程化的初步阶段了,因为使用 babel 需要使用 node.js,毕竟你知道了 node.js 后就会知道 npm 就会知道 webpack 就会知道 create-react-app

所以一般来说接触 React 的同学很快会过度到基于 Node.js 的现代前端工程化开发

关于什么是基于 Node.js 的现代前端工程化开发?也许就是下面的 Vite

基于 Vite 从 0 到 1 启动一个 React 项目

Vite 启动

在进入 Vite 配置之前先做好基于 Node.js 环境的配置

"Node.js" 配置

先找个位置并在终端(或者命令行)初始化一个项目

npm init

初始化后会有一些选项,可以直接回车全部忽略,也可以根据自己意向填写

基于 Vite 从 0 到 1 启动一个 React 项目

选择完成之后

基于 Vite 从 0 到 1 启动一个 React 项目

这个时候系统会创建一个 package.json 文件

基于 Vite 从 0 到 1 启动一个 React 项目

喜欢记录的同学可以添加 git(记得添加 .gitignore 避免添加 node_modules/.vscode/.idea 进入版本依赖)

git init

然后将上面的 HTML 例子的 CDN 切换成 npm 包,比如在终端/命令行执行以下命令

npm install react react-dom

解构 "HTML"

下载完 React 系列套件的依赖后,就需要将上面的 html 例子进行解构,创建 ./src/index.js./src/App.js./index.html

./ 指代当前工作目录(根目录)

将上面的 html 的例子转换成下面的结构

// App.js
import { useState, createElement } from "react";

function App() {
  const [count, setCount] = useState(0);

  const handleClick = () => {
    setCount((count) => count + 1);
  };

  return createElement("div", {
    children: [
      "count:" + count,
      createElement(
        "button",
        {
          key: "2",
          onClick: handleClick,
        },
        "click + 1"
      ),
    ],
  });
}

export default App;
// index.js
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  React.createElement(React.StrictMode, {
    children: [React.createElement(App, { key: "1" })],
  })
);

注意,在 .js 文件中都是使用的 ES Module 而不是 Commonjs 规范是因为此处编写的 .js 将直接在浏览器中运行并且不会配置类似 Webpack 提供的统一规范配置和转换

<!-- index.html -->
<body>
  <div id="root"></div>
</body>
<script src="./src/index.js"></script>

此时的文件目录结构

├── node_modules
├── public
|  └── index.html
├── src
|  ├── App.js 
|  └── index.js
├── package-lock.json
├── package.json

配置 Vite

  1. 下载 Vite 依赖
npm install -D vite
  1. 在根目录创建 Vite 配置文件,vite.config.js
// vite.config.js
import { defineConfig } from "vite";

// https://vitejs.dev/config/
export default defineConfig({
  // root 默认值是 process.cwd(), 即当前工作文件夹
  // index.html 中引用的 .js 需要在同一个 root 目录下
  root: process.cwd(),
  server: {
    port: 5173, // 默认端口是 5173
  },
});

注意,Vite关于运行配置里只有 index.html 需要指定,并不像 webpack 那样需要指定一个 .js 的入口文件,这是因为 Wepback 需要打包模块至一个 .js 文件而 Vite 是采用逐个请求处理后的模块

  1. 配置 package.json 的脚本
{
  // ..
  "scripts": {
    // 新增部分
    "dev": "vite",
  },
  // ...
  "dependencies": {
    "vite": "^3.2.4",
    // ...
  }
  // ...
}
  1. 运行 npm run start,得到预期效果

基于 Vite 从 0 到 1 启动一个 React 项目

配置 JSX

JSXReact 的地位等同于 VueSFC,项目里面不配置一下完全无法展开呀!可以看到上面的 HTML 例子其实使用了 React.createElement 代替 JSX,接下来就为了更好的开发体验配置一下 JSX

  1. 下载 @vitejs/plugin-react 依赖
npm install -D @vitejs/plugin-react
  1. vite.config.js 新增以下内容
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";

export default defineConfig({
  // ...
  plugins: [react()],
});

@vitejs/plugin-react 的底层其实是 @babel/plugin-transform-react-jsx,和 WebpackJSX 配置中 @babel/preset-react 用的是同一个,@vitejs/plugin-react 同样也支持 .babelrcbabel.config.js 配置

  1. 修改项目中关于 React.createElementJSX,并修改文件后缀为 .jsx
// index.js -> index.jsx
// ...
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);
// App.js -> App.jsx
import { useState } from "react";

function App() {
  // ...

  return (
    <div>
      {"count:" + count}
      <button onClick={handleClick}>click + 1</button>
    </div>
  );
}

export default App;
<!-- index.html -->
<body>
  <div id="root"></div>
</body>
<script src="./src/index.jsx"></script>
  1. 运行 npm run start,得到预期效果

基于 Vite 从 0 到 1 启动一个 React 项目

留空问题

在阅读文章的时候可以去思考一些问题,比如

  1. Webpack 在打包的过程中会有转换(transform)的流程,这是 loaderplugin 干的事,比如 .vue to .js,又比如 html-webpack-plugin 会对打包 .js 对静态资源服务的 index.html 的变量自动导入,那么 Vite 是如何解决这些问题的呢?
    1. Vite 实际请求的 module 是否有经过 transform

附带 Vite 原理图

基于 Vite 从 0 到 1 启动一个 React 项目

参考资料

  1. @vitejs/plugin-react - npm