前言
在日常工作中,我大多是在已有的项目基础上进行开发,而非从头构建项目。因此,我期望通过本次学习能填补我在项目初始化阶段知识的空白,与大家共同进步。在此过程中,我欢迎并感激任何指正或建议,无论是关于错误修正还是更优的解决策略,让我们相互促进,共同提升。
环境
在我们正式开发之前,请确认您的计算机已安装Node.js环境,这是进行后续任务的前提。如未安装,请访问Node.js官网(https://nodejs.org/),根据您的操作系统挑选并安装最新版本。安装完毕后,通过在命令行界面分别执行node -v
和npm -v
命令,来检验Node.js及配套的npm(Node Package Manager)是否安装成功。若两命令均返回相应的版本号,即表明Node.js环境已准备就绪,包括npm,为接下来的开发工作奠定了基础。
1. 项目搭建
1.1 初始化
命令如下:
mkdir react-template
cd ./react-template
mkdir public
mkdir src
npm init -y
阅读 npm 文档 以了解有关 package.json 内在机制的更多信息。
1.2 安装webpack和webpack-cli(用于在命令行上运行webpack的工具)
命令如下:
npm install webpack webpack-cli --save-dev
注 --save-dev 开发阶段的依赖,就是我们在开发过程中需要的依赖,只在开发阶段起作用。将添加到package.json的devDependencies中。更多信息
1.3 目录下src文件夹下新建index.js
index.js:
function main() {try {const root = document.getElementById("root");if (root === null) {throw Error("root节点不存在");}root.innerHTML = "1 + 2 = 3;";} catch (error) {console.log(error);}
}
main();
1.4 目录下新建webpack.config.js
webpack配置文件
webpack.config.js:
const path = require("path");
module.exports = {mode: "development",entry: path.resolve(__dirname, "./src/index.js"),output: {path: path.resolve(__dirname, "dist"),filename: "index.bundle.js",},
};
1.5 在package.json的scripts中添加build命令
"scripts": {"build": "webpack","test": "echo \"Error: no test specified\" && exit 1"
}
1.6 执行build命令
npm run build
1.7 在public文件夹下创建index.html并引入index.bundle.js
index.html:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>使用webpack搭建react项目</title></head><body><div id="root"></div><script src="../dist/index.bundle.js"></script></body>
</html>
使用浏览器打开这文件如下:
1.8 安装typescript和相关loader
babel
typescript
babel-with-typescript
命令如下:
npm install --save-dev typescript babel-loader @babel/core @babel/preset-env @babel/preset-typescript
1.9 在目录下新建tsconfig.json和babel.config.json文件
tsconfig.json
babel.config.json
tsconfig.json:
{"compilerOptions": {"outDir": "./dist/","noImplicitAny": true,"module": "es6","target": "es5","jsx": "react","allowJs": true,"moduleResolution": "node","allowSyntheticDefaultImports": true},"include": ["src",],
}
babel.config.json:
{"presets": [["@babel/preset-env",{"targets": {"edge": "17","firefox": "60","chrome": "67","safari": "11.1"},"useBuiltIns": "usage","corejs": "3.6.5"}],"@babel/preset-typescript"]
}
1.10 更新webpack.config.js
webpack.config.js:
const path = require("path");
module.exports = {mode: "development",entry: path.resolve(__dirname, "./src/index.ts"),output: {path: path.resolve(__dirname, "dist"),filename: "index.bundle.js",},resolve: {extensions: [".ts", ".js"],},module: {rules: [{ test: /\.(ts|js)$/, use: "babel-loader", exclude: /node_modules/ },],},
};
1.11 src文件夹下index.js修改为index.ts
index.ts:
function main(elementId: string) {try {const root = document.getElementById(elementId);if (root === null) {throw Error("root节点不存在");}root.innerHTML = "2 + 2 = 4;";} catch (error) {console.log(error);}
}
main("root");
1.12 运行build命令后使用浏览器打开public下index.html文件
1.13 安装react,react-dom,@types/react,@types/react-dom和@babel/preset-react
react
react-dom
@babel/preset-react
npm install react react-dom
npm install --save-dev @babel/preset-react @types/react @types/react-dom
1.14 更新babel.config.json,webpack.config.js
babel.config.json:
{"presets": [["@babel/preset-env",{"targets": {"edge": "17","firefox": "60","chrome": "67","safari": "11.1"},"useBuiltIns": "usage","corejs": "3.6.5"}],"@babel/preset-react","@babel/preset-typescript"]
}
webpack.config.js:
const path = require("path");module.exports = {mode: "development",entry: path.resolve(__dirname, "./src/index.ts"),output: {path: path.resolve(__dirname, "dist"),filename: "index.bundle.js",},resolve: {extensions: [".ts", ".js", ".tsx", ".jsx"],},module: {rules: [{test: /\.(ts|tsx|js|jsx)$/,use: "babel-loader",exclude: /node_modules/,},],},
};
1.15 src文件夹下index.ts修改为index.tsx
index.tsx:
import React from "react";
import { createRoot } from "react-dom/client";const App: React.FC = () => {return <div>2+3=5;</div>;
};const domNode = document.getElementById("root");
const root = createRoot(domNode);
root.render(<App />);
1.16 运行build命令
1.17 安装html-webpack-plugin
html-webpack-plugin
npm install --save-dev html-webpack-plugin
1.18 更新webpack.config.js
webpack.config.js:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");module.exports = {mode: "development",entry: path.resolve(__dirname, "./src/index.tsx"),output: {path: path.resolve(__dirname, "dist"),filename: "index.bundle.js",clean: true,},resolve: {extensions: [".ts", ".js", ".tsx", ".jsx"],},module: {rules: [{test: /\.(ts|tsx|js|jsx)$/,use: "babel-loader",exclude: /node_modules/,},],},plugins: [new HtmlWebpackPlugin({template: path.resolve(__dirname, "./public/index.html"),}),],
};
1.19安装webpack-dev-server
webpack-dev-server
using-webpack-dev-server
npm install --save-dev webpack-dev-server
1.20 在package.json的scripts中添加dev命令
"scripts": {"dev": "webpack server --open","build": "webpack","test": "echo \"Error: no test specified\" && exit 1"
}
1.21 执行dev命令
npm run dev
1.22 将webpack.config.js重名为webpack.dev.js和修改dev命令
"scripts": {"dev": "webpack server --open --config webpack.dev.js","build": "webpack","test": "echo \"Error: no test specified\" && exit 1"
}
1.23 安装webpack-merge
webpack-merge
npm install --save-dev webpack-merge
1.24 新建webpack.common.js
webpack.common.js:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");module.exports = {entry: path.resolve(__dirname, "./src/index.tsx"),output: {path: path.resolve(__dirname, "dist"),filename: "index.bundle.js",clean: true,},resolve: {extensions: [".ts", ".js", ".tsx", ".jsx"],},module: {rules: [{test: /\.(ts|tsx|js|jsx)$/,use: "babel-loader",exclude: /node_modules/,},],},plugins: [new HtmlWebpackPlugin({template: path.resolve(__dirname, "./public/index.html"),}),],
};
1.25 修改webpack.dev.js
devtool
const { merge } = require("webpack-merge");
const common = require("./webpack.common.js");module.exports = merge(common, {mode: "development",devtool: "inline-source-map",
});
1.26 运行dev命令
1.27 新建webpack.prod.js
webpack.prod.js:
const { merge } = require("webpack-merge");
const common = require("./webpack.common.js");module.exports = merge(common, {mode: "production",
});
1.28 更新build命令
"scripts": {"dev": "webpack server --open --config webpack.dev.js","build": "webpack --config webpack.prod.js","test": "echo \"Error: no test specified\" && exit 1"
}
1.29 执行build命令
截至目前为止目录结构
1.30安装style-loader,css-loader,less-loader和less
style-loader
css-loader
less-loader
less
npm install less less-loader style-loader css-loader --save-dev
1.31 更新webpack.common.js
webpack.common.js:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");module.exports = {entry: path.resolve(__dirname, "./src/index.tsx"),output: {path: path.resolve(__dirname, "dist"),filename: "index.bundle.js",clean: true,},resolve: {extensions: [".ts", ".js", ".tsx", ".jsx"],},module: {rules: [{test: /\.less$/i,use: ["style-loader", "css-loader", "less-loader"],},{test: /\.(ts|tsx|js|jsx)$/,use: "babel-loader",exclude: /node_modules/,},],},plugins: [new HtmlWebpackPlugin({template: path.resolve(__dirname, "./public/index.html"),}),],
};
1.32 在src文件夹下新建App.tsx,app.less文件
App.tsx:
import React, { useMemo } from "react";
import "./app.less";
export const App: React.FC = () => {return useMemo(() => {return <div className="red">App</div>;}, []);
};export default App;
app.less:
@red: red;
.red {color: @red;
}
1.33 修改index.tsx文件
index.tsx:
import React from "react";
import { createRoot } from "react-dom/client";
import App from "./App";const domNode = document.getElementById("root");
const root = createRoot(domNode);
root.render(<App />);
1.34 执行dev命令
1.35 更新webpack.common.js:
webpack.common.js:
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");module.exports = {entry: path.resolve(__dirname, "./src/index.tsx"),output: {path: path.resolve(__dirname, "dist"),filename: "index.bundle.js",clean: true,},resolve: {extensions: [".ts", ".js", ".tsx", ".jsx"],},module: {rules: [{test: /\.(png|svg|jpg|jpeg|gif)$/i,type: "asset/resource",},{test: /\.less$/i,use: ["style-loader", "css-loader", "less-loader"],},{test: /\.(ts|tsx|js|jsx)$/,use: "babel-loader",exclude: /node_modules/,},],},plugins: [new HtmlWebpackPlugin({template: path.resolve(__dirname, "./public/index.html"),}),],
};
1.36 在根目录下新建images.d.ts声明文件
declaration-files
images.d.ts:
declare module "*.svg";
declare module "*.png";
declare module "*.jpg";
declare module "*.jpeg";
declare module "*.gif";
1.37 更新tsconfig.json
tsconfig.json:
{"compilerOptions": {"outDir": "./dist/","noImplicitAny": true,"module": "es6","target": "es5","jsx": "react","allowJs": true,"moduleResolution": "node","allowSyntheticDefaultImports": true},"include": ["src","images.d.ts",],
}
1.38 在src目录下添加张图片并在App.tsx中引入
App.tsx:
import React, { useMemo } from "react";
import icon from "./app.jpg";
import "./app.less";
export const App: React.FC = () => {return useMemo(() => {return (<div className="red"><img src={icon} /></div>);}, []);
};export default App;
总结
本次搭建参考webpack官网指南,本文如有错误欢迎指出。