使用webpack5從0到1搭建一個react項(xiàng)目的實(shí)現(xiàn)步驟
前言
在這之前,每開始一個新項(xiàng)目我都是使用現(xiàn)有的腳手架,這非常便于快速地啟動一個新項(xiàng)目,而且通用的腳手架通??紤]地更加全面,也有利于項(xiàng)目的穩(wěn)定開發(fā);不過對于一個小項(xiàng)目,根據(jù)需求自己搭建可能會更好,一方面小項(xiàng)目不需要腳手架那么豐富的功能,另一方面可以提高對項(xiàng)目的掌控度以方便后期的擴(kuò)展。
這篇文章是在實(shí)踐中總結(jié)的,具有實(shí)操性,讀者可跟著一步步進(jìn)行搭建,中間我會穿插一些原理,當(dāng)然因?yàn)楣P者的能力有限,不會特別深入。
預(yù)備知識
- 熟悉Javascript && HTML && CSS
- 熟悉ES6+
- 有能力搭建Nodejs環(huán)境
- 會用命令行
目標(biāo)
學(xué)習(xí)使用webpack5和為什么使用它
用webpack5搭建開發(fā)環(huán)境
用webpack5搭建生產(chǎn)環(huán)境
什么是webpack
這有點(diǎn)老生常談了,不過為了新同學(xué)能夠看下去,在這里簡單介紹一下。一個現(xiàn)代化的web應(yīng)用,已經(jīng)不是單純地優(yōu)html、css、javascript組成的,它還需要對應(yīng)用進(jìn)行打包、壓縮和編譯成瀏覽器能夠理解的代碼,于是webpack就開始流行起來了。
webpack是一個模塊打包器,它可以打包任何東西。你可以在開發(fā)時使用最新的Javascript特性或Typescirpt,webpack會將它編譯成瀏覽器支持的代碼并壓縮它;你還可以在Javascript中導(dǎo)入需要用到的靜態(tài)資源。
在開發(fā)過程中,webpack提供了開發(fā)服務(wù)器并支持HMR,什么是HMR和怎么配置后面會詳細(xì)介紹,現(xiàn)在我們只要知道當(dāng)我們保存代碼的時候webpack會幫我們自動重新編譯和刷新瀏覽器。
webpack的能做的遠(yuǎn)不止這些,這篇文章主要是幫助你熟悉基本概念和如何去配置自己的腳手架。
開始搭建
這篇文章算是一個較為完整的實(shí)戰(zhàn)教程,目標(biāo)是搭建一個可用的腳手架,在此基礎(chǔ)上可以擴(kuò)展出更多的功能。
架構(gòu)需要支持的特性
- Webpack5
- 命令行友好提示
- es6+
- React
- Typescript
- PostCSS + cssnext
- HMR
安裝webpack
新建一個項(xiàng)目,進(jìn)入項(xiàng)目根目錄,創(chuàng)建默認(rèn)的package.json
yarn init -y
安裝webpack和webpack-cli
- webpack - 模塊打包庫
- webpack-cli - 命令行工具
yarn add webpack webpack-cli -D
基礎(chǔ)配置
在根目錄下新建一個webpack.config.js
Entry
入口文件,webpack會首先從這里開始編譯
// webpack.config.js
const path = require('path');
module.exports = {
entry: {
app: './src/index.js'
},
}
Output
定義了打包后輸出的位置,以及對應(yīng)的文件名。[name]是一個占位符,這里是根據(jù)我們在entry中定義的key值,即等價于app
module.exports = {
/* ... */
output: {
path: path.resolve(__dirname, './dist'),
filename: '[name].bundle.js',
},
}
確保src下有index.js,然后現(xiàn)在可以使用我們的最小化配置進(jìn)行打包。在package.json中加入以下代碼
"scripts": {
"build": "webpack"
}
運(yùn)行該命令
yarn run build
可以在命令行中看到打包的結(jié)果,并且在根目錄下生成了一個dist目錄,說明打包成功。
Plugins
插件使webpack具備可擴(kuò)展性,可以讓我們支持更多的功能。
模板文件
當(dāng)我們構(gòu)建一個web app的時候,我們需要一個HTML頁,然后再HTML中引入Javascript,當(dāng)我們配置了打包輸出的bundle文件是隨機(jī)字符串時,每次手動更新就特別麻煩,所以最好的方法是可以自動將bundle打包進(jìn)HTML中。
Html-webpack-plugin - 從模板生成一個HTML文件
安裝
yarn add html-webpack-plugin -D
在根目錄下新建一個文件public/index.html,內(nèi)容如下
<!DOCTYPE html> <html lang="en"> <head> <title><%= htmlWebpackPlugin.options.title %></title> </head> <body> <div id="root"></div> </body> </html>
其中title是讀取html-webpack-plugin插件的配置,配置如下
// webpack.config.js
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
/* ... */
plugins: [
new HtmlWebpackPlugin({
title: '鐵木真大屏展示',
template: path.resolve(__dirname, './public/index.html'),
filename: 'index.html',
}),
],
}
現(xiàn)在我們再次運(yùn)行yarn run build,可以看到dist下多了一個index.html,其中自動插入了標(biāo)題和script,效果如下

打包前清除dist
clean-webpack-plugin - 打包前移除/清理 打包目錄
安裝
yarn add clean-webpack-plugin -D
配置
const path = require('path')
const {CleanWebpackPlugin} = require('clean-webpack-plugin')
module.exports = {
/* ... */
plugins: [
/* ... */
new CleanWebpackPlugin(),
],
}
命令行友好提示
安裝
yarn add friendly-errors-webpack-plugin -D
配置
// webpack.config.js
const friendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');
module.exports = {
plugins: [
new friendlyErrorsWebpackPlugin(),
]
}
Loaders
webpack使用loaders去解析模塊,webpack想要去如何理解Javascript、靜態(tài)資源(圖片、字體、css)、轉(zhuǎn)移Typescript和Babel,都需要配置相應(yīng)的loader規(guī)則。
在項(xiàng)目中只有一個HTML和一些Javascript是沒什么用的,我們還需要webpack能夠做一些事:
- 將最新的Javascript特性編譯成瀏覽器理解的
- 模塊化CSS,將編譯SCSS、cssnext編譯成CSS
- 導(dǎo)入圖片、字體等靜態(tài)資源
- 使用自己喜愛的框架,如React
Babel
Babel 是一個 JavaScript 編譯器,能將 ES6 代碼轉(zhuǎn)為 ES5 代碼,讓你使用最新的語言特性而不用擔(dān)心兼容性問題,并且可以通過插件機(jī)制根據(jù)需求靈活的擴(kuò)展,我們需要先安裝以下庫
yarn add babel-loader @babel/core -D
- babel-loader - 使用Babel和webpack轉(zhuǎn)譯文件
- @babel/core - 轉(zhuǎn)譯ES2015+的代碼
配置如下
// webpack.config.js
module.exports = {
/* ... */
module: {
rules: [
// JavaScript
{
test: /\.m?js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env'],
},
},
},
],
},
}
在 Babel 執(zhí)行編譯的過程中,會從項(xiàng)目根目錄下的配置文件讀取配置。在根目錄下創(chuàng)建Babel的配置文件babel.config.json
{
"presets": ["@babel/preset-env"]
}
如果未安裝@babel/preset-env需要先安裝
yarn add @babel/preset-env -D
圖片和字體
解析圖片的loader配置
module.exports = {
/* ... */
module: {
rules: [
// Images
{
test: /\.(?:ico|gif|png|jpg|jpeg)$/i,
type: 'asset/resource',
},
],
},
}
解析字體文件的loader配置
module.exports = {
/* ... */
module: {
rules: [
// Fonts and SVGs
{
test: /\.(woff(2)?|eot|ttf|otf|svg|)$/,
type: 'asset/inline',
},
],
},
}
樣式
現(xiàn)在我們希望能夠在Javascript中導(dǎo)入CSS,以及將CSS注入DOM,另外還想使用CSS的高級特性,如cssnext,需要依賴一下庫
- css-loader - 解析CSS導(dǎo)入
- style-loader - 將CSS注入DOM
- postcss-loader - 用PostCSS處理CSS
- postcss-preset-env - PostCSS的默認(rèn)配置
- postcss - PostCSS 是一個允許使用 JS 插件轉(zhuǎn)換樣式的工具。 這些插件可以檢查(lint)你的 CSS,支持 CSS Variables 和 Mixins, 編譯尚未被瀏覽器廣泛支持的先進(jìn)的 CSS 語法,內(nèi)聯(lián)圖片,以及其它很多優(yōu)秀的功能。
- postcss-next - PostCSS的插件,可以使用CSS最新的語法
安裝
yarn add css-loader style-loader postcss-loader postcss-preset-env postcss postcss-cssnext -D
新建PostCSS配置文件postcss.config.js,配置如下
module.exports = {
plugins: {
'postcss-preset-env': {
browsers: 'last 2 versions',
},
},
}
配置loader
// webpack.config.js
module.exports = {
/* ... */
module: {
rules: [
// CSS, PostCSS, and Sass
{
test: /\.(scss|css)$/,
use: ['style-loader', {
loader: 'css-loader',
options: {
importLoaders: 1,
},
}, 'postcss-loader'],
},
],
},
}
開發(fā)環(huán)境
讓我們從設(shè)置配置為開發(fā)模式開始,表示當(dāng)前的配置的配置為開發(fā)環(huán)境的配置
// webpack.config.js
module.exports = {
mode: 'development',
// ...
}
使用source maps
為了在報錯的時候更好的追蹤代碼和給出錯誤代碼出現(xiàn)的地方的提示,我們可以使用source map,配置如下
// webpack.config.js
module.exports = {
devtool: 'inline-source-map'
// ...
}
HMR
當(dāng)我們改動代碼時,希望能自動重新編譯代碼,webpack提供了三種不同的方式:
- 監(jiān)聽模式
- webpack-dev-server
- webpack-dev-middleware
大多數(shù)情況,使用的是webpack-dev-server,本文也是使用這個,不過我會順帶介紹一下其它兩種方式,大家各取所需。
使用監(jiān)聽模式:
// package.json
{
"watch": "webpack --watch"
}
執(zhí)行以下命令
yarn run watch
現(xiàn)在當(dāng)我們保存代碼的時候會自動編譯代碼,刷新瀏覽器后即可看到效果;但是我們想要自動刷新瀏覽器怎么辦,這時候就輪到webpack-dev-server商場了。
webpack-dev-server
它為我們提供了一個服務(wù)器和live relaoding的能力,我們需要首先安裝它
yarn add webpack-dev-server -D
然后配置如下
// webpack.config.js
module.exports = {
// ...
devServer: {
historyApiFallback: true,
contentBase: path.join(__dirname, './dist'),
open: false,
hot: true,
quiet: true,
port: 8082,
},
}
// package.json
{
"scripts": {
"start": "webpack serve"
}
}
我們在8082端口監(jiān)聽了一個服務(wù),監(jiān)聽的目錄是dist,并且支持HMR,現(xiàn)在打開http://localhost:8082,可以看到我們的頁面,然后改動代碼,瀏覽器會自動刷新更新效果,是不是很酷!
上面提到了HMR,它的全稱是Hot Module Replacement,翻譯過來就是熱模塊替換,我認(rèn)為它是webpack提供的最有用的一個特性,它允許我們只更新改動過的模塊,而不需有全部更新,我們在上面已經(jīng)開啟了該功能,即hot: true。
webpack-dev-middleware
這是一個webpack的中間件,可以讓webpack把文件交給一個服務(wù)器處理,比如接下來要使用的express,這給了我們更多的控制權(quán),接下來簡單演示一下。
安裝express和webpack-dev-middleware
yarn add express webpack-dev-middleware -D
更改配置
module.exports = {
//...
output: {
//...
publicPath: '/'
}
}
publicPath可以定義了express監(jiān)聽服務(wù)的路徑,接下來就創(chuàng)建我們的express`服務(wù)器
新建一個server.js
const express = require('express');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const app = express();
const config = require('./webpack.config.js');
const compiler = webpack(config);
// Tell express to use the webpack-dev-middleware and use the webpack.config.js
// configuration file as a base.
app.use(
webpackDevMiddleware(compiler, {
publicPath: config.output.publicPath,
})
);
// Serve the files on port 3000.
app.listen(3000, function () {
console.log('Example app listening on port 3000!\n');
});
監(jiān)聽端口為3000,執(zhí)行以下命令啟動服務(wù)
node server.js
方便起見,可以將該命令加入package.json
{
//...
"scripts": {
"server": "node server.js"
}
}
使用Typescript
安裝依賴
yarn add typescript ts-loader -D
在根目錄下創(chuàng)建typescript的配置文件tsconfig.json,具體配置如下
{
"compilerOptions": {
"outDir": "./dist/",
// "rootDir": "./src",
"sourceMap": true, // 開啟sourcemap
"module": "commonjs",
"target": "es5",
"jsx": "react",
"esModuleInterop": true,
"allowJs": true,
"strict": true
}
}
// webpack.config.js
module.exports = {
//...
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
]
}
}
使用React
在上面配置typescript中,已經(jīng)開啟了支持react,現(xiàn)在只需安裝react的依賴即可
yarn add react react-dom @types/react @types/react-dom
然后將入口文件改成.tsx后綴,內(nèi)容如下
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
const App = () => {
return <div>hello world2</div>;
};
ReactDOM.render(<App />, document.getElementById('root'));
代碼規(guī)范
Prettier
Prettier是一個誕生于2016年就迅速流行起來的專注于代碼格式化的工具。出道即巔峰啊-.-
Prettier只關(guān)注格式化,并不具有l(wèi)int檢查語法等能力。它通過解析代碼并匹配自己的一套規(guī)則,來強(qiáng)制執(zhí)行一致的代碼展示格式。
它在美化代碼方面有很大的優(yōu)勢,配合ESLint可以對ESLint格式化基礎(chǔ)上做一個很好的補(bǔ)充。
使用
以VSCode為例,安裝Prettier插件即可使用,如果想自定義配置,可以cmd+,快捷鍵進(jìn)入vscode配置,搜索Prettier找到對應(yīng)的配置項(xiàng)進(jìn)行配置。
Eslint
ESLint 是一個在 JavaScript 代碼中通過規(guī)則模式匹配作代碼識別和報告的插件化的檢測工具,它的目的是保證代碼規(guī)范的一致性和及時發(fā)現(xiàn)代碼問題、提前避免錯誤發(fā)生。
ESLint 的關(guān)注點(diǎn)是代碼質(zhì)量,檢查代碼風(fēng)格并且會提示不符合風(fēng)格規(guī)范的代碼。除此之外 ESLint 也具有一部分代碼格式化的功能。
安裝依賴,方便起見,直接使用已有的Eslint配置,這里使用的是fabric
yarn add @umijs/fabric -D
根目錄下新建.eslintrc.js,配置如下
module.exports = {
extends: [require.resolve('@umijs/fabric/dist/eslint')],
globals: {},
plugins: ['react-hooks'],
rules: {
'no-restricted-syntax': 0,
'no-param-reassign': 0,
'no-unused-expressions': 0,
},
};
重啟編輯器,即可應(yīng)用Eslint的配置。
總結(jié)
到目前為止,我們搭建了一個簡易的react腳手架,并且它支持typescript、cssnext、HMR等特性,對于一個小項(xiàng)目來說已經(jīng)足夠用了,大家可以在此基礎(chǔ)上進(jìn)行擴(kuò)展;后面有時間的話會和大家一起討論一下webpack稍底層的原理,是從源碼的角度去看。
附錄
how-to-use-webpack
webpack官網(wǎng)
到此這篇關(guān)于使用webpack5從0到1搭建一個react項(xiàng)目的實(shí)現(xiàn)步驟的文章就介紹到這了,更多相關(guān)webpack5搭建react項(xiàng)目內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
詳解在React中跨組件分發(fā)狀態(tài)的三種方法
這篇文章主要介紹了詳解在React中跨組件分發(fā)狀態(tài)的三種方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-08-08
React18系列reconciler從0實(shí)現(xiàn)過程詳解
這篇文章主要介紹了React18系列reconciler從0實(shí)現(xiàn)過程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01
使用react-virtualized實(shí)現(xiàn)圖片動態(tài)高度長列表的問題
一般我們在寫react項(xiàng)目中,同時渲染很多dom節(jié)點(diǎn),會造成頁面卡頓, 空白的情況。為了解決這個問題,今天小編給大家分享一篇教程關(guān)于react-virtualized實(shí)現(xiàn)圖片動態(tài)高度長列表的問題,感興趣的朋友跟隨小編一起看看吧2021-05-05
react 移動端實(shí)現(xiàn)列表左滑刪除的示例代碼
這篇文章主要介紹了react 移動端實(shí)現(xiàn)列表左滑刪除的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07
React獲取Java后臺文件流并下載Excel文件流程解析
這篇文章主要介紹了React獲取Java后臺文件流下載Excel文件,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-06-06
關(guān)于?React?中?useEffect?使用問題淺談
本文主要介紹了關(guān)于React中useEffect使用問題淺談,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-06-06

