问:目前前端最火的两大框架react和vue官方都有自己的成熟的cli脚手架,为什么还要自己搭建脚手架了? 答: 一、自己搭建脚手架可以根据自己公司的项目特征来决定使用哪些具体的插件或者编译方式,官方的脚手架都是大众化的,大而全的,所以自己搭建的更灵活。 二、装逼
不管你是哪种原因,本教程都适用
一、初始化项目
- 创建好自己的项目存放目录,在终端进入该目录
- 命令行中输入以下命令,会自动创建好项目的package.json文件
npm init -y
- package.json中需要做基础修改
{
"name": "react-cli",
"version": "1.0.0",
"description": "",
-"main": "index.js",
+"private":true,
"scripts": {
-"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
-
项目目录结构搭建,这是我的的项目目录 -
安装webpack、webpack-cli、webpack-merge、webpack-dev-server、html-webpack-plugin webpack:官方的处理包,打包什么的都需要这个来执行
webpack-cli:能够在命令行中使用webpack命令
webpack-merge:在开发环境和生产环境中的打包配置项有所不同,通过这个来合并两个环境中相同的配置项
webpack-dev-server:本地服务器,能够边开发浏览器自动刷新页面或HMR(热模块替换)
html-webpack-plugin:模板文件插件
在终端命令行中输入以下命令:
npm install webpack webpack-cli webpack-merge webpack-dev-server html-webpack-plugin -D
- 在项目根目录下创建三个webpack配置文件,webpack.common.js(公用的配置项)、webpack.dev.js(开发环境配置项)、webpack.prod.js(生产环境配置项)
二、react 项目相关的包安装
-
本地需要用的包:babel-loader、@babel/core、@babel/preset-env、@babel/preset-react、@pmmmwh/react-refresh-webpack-plugin、react-refresh、css-loader、style-loader、sass、sass-loader、mini-css-extract-plugin babel-loader:js文件使用的loader
@babel/core:调用babel进行代码处理
@babel/preset-env:将es6+的代码转换成兼容的es5代码
@babel/preset-react:识别react中jsx的写法进行转换
@pmmmwh/react-refresh-webpack-plugin:react 的HMR(热模块更新)插件,依赖于react-refresh
react-refresh:react 的HMR(热模块更新)
css-loader:识别css文件,并将css代码转换成js代码
style-loader:将js代码中的css代码添加到head中,使用style标签的方式
sass:编译scss/sass
sass-loader:识别sass/scss文件
mini-css-extract-plugin:在生产环境下替代style-loader,可以将css代码转换成css文件形式
在终端命令行中输入以下命令:
npm install babel-loader @babel/core @babel/preset-env @babel/preset-react react-refresh @pmmmwh/react-refresh-webpack-plugin css-loader style-loader sass sass-loader mini-css-extract-plugin -D
-
生产环境下需要用到的包:react、react-dom、react-router-dom react:处理react项目程序
react-dom:渲染dom树
react-router-dom:react路由
在终端命令行中输入以下命令
npm install react react-dom react-router-dom --save
三、webpack配置文件代码编写
- 在src目录下添加入口文件:
- 入口文件中写入react的代码
import ReactDom from "react-dom/client";
function App(){
return(
<div>
测试
</div>
)
}
const root=ReactDom.createRoot(document.getElementById("root"));
root.render(
<App />
);
- 根目录新建public文件夹,并添加html模板文件,咱们在入口文件里面写的需要找id为root的元素,所以模板文件里面必须存在一个root id 的标签
- webpack.common.js代码
const path=require("path");
const HtmlWebpackPlugin=require("html-webpack-plugin");
module.exports={
entry:{
app:"./src/index.js"
},
output: {
path:path.resolve(__dirname,"dist"),
clean:true
},
module: {
rules:[
{
test:/\.(jpg|png|gif|svg)$/,
type:"asset",
parser:{
dataUrlCondition:{
maxSize:100*1024
}
},
generator:{
filename:"static/images/[name]_[contenthash:8][ext]"
}
}
]
},
plugins:[
new HtmlWebpackPlugin({
template:"./public/index.html",
minify:{
collapseWhitespace:true,
removeComments: true
}
})
]
}
- webpack.dev.js代码
const {merge}=require("webpack-merge");
const common=require("./webpack.common.js");
const ReactRefreshPlugin=require("@pmmmwh/react-refresh-webpack-plugin");
module.exports=merge(common,{
mode:"development",
output:{
filename:"[name].js",
publicPath:"/"
},
devtool:"inline-source-map",
devServer:{
open:true,
compress:true,
port:"auto",
client:{
logging:"none",
progress: true
},
historyApiFallback:true,
},
module:{
rules:[
{
test:/\.(css|scss|sass)$/,
use:[
"style-loader",
"css-loader",
"sass-loader"
]
},
{
test:/\.(js|jsx)$/,
exclude:"/node_modules/",
use:[
{
loader:"babel-loader",
options:{
presets:[
"@babel/preset-env",
["@babel/preset-react",{
"runtime":"automatic"
}]
],
plugins: [require.resolve("react-refresh/babel")]
}
}
]
}
]
},
plugins: [
new ReactRefreshPlugin()
]
})
- webpack.prod.js代码
const {merge}=require("webpack-merge");
const common=require("./webpack.common.js");
const MiniCssExtractPlugin=require("mini-css-extract-plugin");
module.exports=merge(common,{
mode:"production",
output:{
filename:"static/js/[name].[contenthash:8].js",
publicPath:"./"
},
devtool:"source-map",
module:{
rules:[
{
test:/\.(css|scss|sass)$/,
use:[
{
loader:MiniCssExtractPlugin.loader,
options:{
publicPath:"../../"
}
},
"css-loader",
"sass-loader"
]
},
{
test:/\.(js|jsx)$/,
exclude:"/node_modules/",
use:[
{
loader:"babel-loader",
options:{
presets:[
"@babel/preset-env",
["@babel/preset-react",{
"runtime":"automatic"
}]
]
}
}
]
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename:"static/css/[name]_[contenthash:8].css"
}),
]
})
四、页面运行测试
- 在package.json里面的scripts中添加运行命令
{
"name": "react-cli",
"version": "1.0.0",
"description": "",
"private": true,
"scripts": {
+ "start": "webpack serve --config webpack.dev.js",
+ "build": "webpack --config webpack.prod.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.18.6",
"@babel/preset-env": "^7.18.6",
"@babel/preset-react": "^7.18.6",
"@pmmmwh/react-refresh-webpack-plugin": "^0.5.7",
"babel-loader": "^8.2.5",
"css-loader": "^6.7.1",
"html-webpack-plugin": "^5.5.0",
"mini-css-extract-plugin": "^2.6.1",
"react-refresh": "^0.14.0",
"sass": "^1.53.0",
"sass-loader": "^13.0.2",
"style-loader": "^3.3.1",
"webpack": "^5.73.0",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.9.3",
"webpack-merge": "^5.8.0"
},
"dependencies": {
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.3.0"
}
}
- 在终端命令行中输入以下命令:
npm run start
妥妥的没问题 3. 添加路由页面,在src下pages文件下添加两个页面文件,然后在路由js文件中引入
import { BrowserRouter,Routes,Route } from "react-router-dom";
import Page1 from "../pages/page1/index";
import Page2 from "../pages/page2/index";
export default function App(){
return(
<BrowserRouter>
<Routes>
<Route path="/" element={<Page1 />}></Route>
<Route path="/page2" element={<Page2 />}></Route>
</Routes>
</BrowserRouter>
)
}
- 在入口文件中,引入路由js
import ReactDom from "react-dom/client";
import App from "./routers/index";
const root=ReactDom.createRoot(document.getElementById("root"));
root.render(
<App />
);
哦了,完活,后面自己想要添加eslint或者postcss自己添加就可了,然后根据自己的项目添加对应的插件。
手真白。。呸。。破键盘,手收回去吧,教完了~
|