问:目前前端最火的两大框架react和vue官方都有自己的成熟的cli脚手架,为什么还要自己搭建脚手架了?
答:
一、自己搭建脚手架可以根据自己公司的项目特征来决定使用哪些具体的插件或者编译方式,官方的脚手架都是大众化的,大而全的,所以自己搭建的更灵活。
二、装逼
不管你是哪种原因,本教程都适用
npm init -y
{
"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
本地需要用的包: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
import ReactDom from "react-dom/client";
function App(){
return(
<div>
测试
</div>
)
}
const root=ReactDom.createRoot(document.getElementById("root"));
root.render(
<App />
);
const path=require("path"); //node环境当前路径
const HtmlWebpackPlugin=require("html-webpack-plugin"); //模板文件插件,能够自动将打包的css和js加入到模板文件中
module.exports={
entry:{
app:"./src/index.js" //找到咱们刚才在src下面的入口文件
},
output: {
path:path.resolve(__dirname,"dist"), //打包文件输出的地址
clean:true //webpack5新增的,每次打包前删除旧的dist包文件
},
module: {
rules:[
{
test:/\.(jpg|png|gif|svg)$/, //处理图片文件打包
type:"asset", //webpack5新增的处理静态资源的loader,替换之前的url-loder、file-loader,具体的可以官方文档
parser:{
dataUrlCondition:{
maxSize:100*1024 //最大100kb的文件会被转成base64,大于100kb的文件会转成图片文件
}
},
generator:{
filename:"static/images/[name]_[contenthash:8][ext]" //最终图片文件输出的路径
}
}
]
},
plugins:[
new HtmlWebpackPlugin({
template:"./public/index.html", //找到咱们刚才创建的模板文件
minify:{ //压缩html
collapseWhitespace:true, //移除空格
removeComments: true // 移除注释
}
})
]
}
const {merge}=require("webpack-merge"); //引入merge工具
const common=require("./webpack.common.js"); //引入刚才写的公共的webpack.common.js文件
const ReactRefreshPlugin=require("@pmmmwh/react-refresh-webpack-plugin");
//使用merge,可以把common里面写的所有配置项都合并过来,然后再单独写在开发环境下需要的配置即可
module.exports=merge(common,{
mode:"development", //当前环境变量
output:{
filename:"[name].js", //开发环境没有缓存问题,所以不需要添加hash值,添加了会影响编译速度
publicPath:"/" //公共路径,开发环境写根目录即可
},
devtool:"inline-source-map", //开发开启source-map,方便开发有错误时定位文件位置
devServer:{ //本地服务器
open:true, //是否自动打开浏览器
compress:true,
port:"auto", //端口号,可以自定义也可以写成auto
client:{
logging:"none",
progress: true
},
historyApiFallback:true,
},
module:{
rules:[
{
test:/\.(css|scss|sass)$/,
use:[ //loader 顺序是自下而上执行,所以顺序一定不要错
"style-loader",
"css-loader", //如果需要使用css module模式的话,在这个loader里面添加配置即可,自己百度下
"sass-loader"
]
},
{
test:/\.(js|jsx)$/,
exclude:"/node_modules/", //处理js文件,剔除node_modules文件里面的文件
use:[
{
loader:"babel-loader",
options:{
presets:[
"@babel/preset-env",
["@babel/preset-react",{
"runtime":"automatic"
}]
],
plugins: [require.resolve("react-refresh/babel")] //HMR 热模块更新
}
}
]
}
]
},
plugins: [
new ReactRefreshPlugin()
]
})
const {merge}=require("webpack-merge"); //引入merge工具
const common=require("./webpack.common.js"); //引入刚才写的公共的webpack.common.js文件
const MiniCssExtractPlugin=require("mini-css-extract-plugin");
//使用merge,可以把common里面写的所有配置项都合并过来,然后再单独写在生产环境下需要的配置即可
module.exports=merge(common,{
mode:"production", //当前环境变量
output:{
filename:"static/js/[name].[contenthash:8].js", //将js文件放到对应的目录下,并使用hash值命名,当js内容修改后,文件名也会对应修改
publicPath:"./" //公共路径,生产环境写相对路径,这样前端页面放到其他的目录下的时候不会出现白屏问题
},
devtool:"source-map", //生产环境下用的source map 模式
module:{
rules:[
{
test:/\.(css|scss|sass)$/,
use:[ //loader 顺序是自下而上执行,所以顺序一定不要错
{
loader:MiniCssExtractPlugin.loader,
options:{
publicPath:"../../" //这个路径是控制打包的css文件里面写的路径,因为把css文件放到了static/css文件下了,所以需要重置下css里面的公共路径配置
}
},
"css-loader", //如果需要使用css module模式的话,在这个loader里面添加配置即可,自己百度下
"sass-loader"
]
},
{
test:/\.(js|jsx)$/,
exclude:"/node_modules/", //处理js文件,剔除node_modules文件里面的文件
use:[
{
loader:"babel-loader",
options:{
presets:[
"@babel/preset-env",
["@babel/preset-react",{
"runtime":"automatic"
}]
]
//生产环境下不需要HRM热模块更新,所以去掉
}
}
]
}
]
},
plugins: [
new MiniCssExtractPlugin({
filename:"static/css/[name]_[contenthash:8].css" //配置css文件输出路径
}),
]
})
{
"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>
)
}
import ReactDom from "react-dom/client";
// 引入路由js
import App from "./routers/index";
const root=ReactDom.createRoot(document.getElementById("root"));
root.render(
<App />
);
哦了,完活,后面自己想要添加eslint或者postcss自己添加就可了,然后根据自己的项目添加对应的插件。
手真白。。呸。。破键盘,手收回去吧,教完了~