前言
react+webpack4搭建前端項目分為三個章節。鏈接如下。目的是實現從零搭建一個react后臺管理系統
1、react+webpack4搭建前端項目(一)基礎項目搭建
2、react+webpack4搭建前端項目(二)react全家桶的使用
3、react+webpack4搭建前端項目(三)打包優化
webpack配置的講解
4、react+webpack4.x搭建前端項目(四)配置抽取和區分環境
5、react+webpack4.x搭建前端項目(五)多頁面配置
6、react+webpack4.x多模塊打包配置
這是第一章,基本項目搭建
本篇主要講述一步步搭建react
項目雛形(不使用create-react-app
,umi
等),包括配置基本webpack,再到react+webpack
配置整合,到完成項目的啟動和打包(不包含react
相關技術棧的使用和webpack
的打包優化)。這些東西我還會在之后更新新的文章來詳細講解react
相關技術棧(全家桶react+react-router+axios+antd+mobx
)的使用以及webpack
打包優化
本文適合人群:react,webpack有一定基礎
技術棧
- react框架:
react+react-router+axios+antd+mobx
后邊在寫項目中會使用,本文不涉及 - 打包構建
webpack4.x
廢話不多說,前方高能,正式開始嘍
初始化項目
webpack安裝(webpack小試牛刀)
創建package.json,執行
npm init
一路按enter鍵就搞定了-
安裝webpack基本包(本文采用webpack4.x,注意了啊,各位同學)
npm install --D webpack webpack-dev-server webpack-cli
webpack4.x
必須安裝webapck-cli
,這是一個注意事項
新建src/index.js
,添加代碼如下
console.log("hello world")
在package.json
執行腳本添加"build":"webpack"
在終端執行npm run build
,可以看到在根目錄生成了dist/main.js的打包文件,這是webpack4.x打包默認找src/index.js打包入口,如下圖:
上邊已經說明webpack在本項目中可以成功構建打包js文件了,其它用法請查看官方文檔!
下邊開始正式配置webpack啦~
一步步從最基本的配置出發,到創建不同環境webpack配置文件來區分不同環境,在到詳細配置不同環境的webpack;最后配置react的開發和打包環境
webpack的基礎配置
1、項目根目錄創建build目錄,創建webpack.config.js
基本配置
const path = require("path");
function resolve(dir) {
return path.resolve(__dirname, dir)
}
module.exports = {
// 指定構建環境
mode:"development",
// 入口
entry: {
app: "./src/index"
},
// 出口
output: {
path : resolve("../dist"),
filename: "js/[name].[hash].js",
publicPath: "/" // 打包后的資源的訪問路徑前綴
},
// 模塊
module:{
},
// 插件
plugins:[
],
// 開發環境本地啟動的服務配置
devServer: {
}
}
上邊每一項配置都有注釋,有什么不懂的基本配置可以看官方文檔
2、編寫,配置html模板,實現html模板的打包,安裝插件
npm install -D html-webpack-plugin
在根目錄創建index.html
模板,代碼很簡單
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>mydemo</title>
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
3、在webpack.config.js的plugins添加
new HtmlWebpackPlugin({
filename: resolve('./../dist/index.html'), // html模板的生成路徑
template: 'index.html',//html模板
inject: true, // true:默認值,script標簽位于html文件的 body 底部
hash: true, // 在打包的資源插入html會加上hash
// html 文件進行壓縮
minify: {
removeComments: true, //去注釋
collapseWhitespace: true, //壓縮空格
removeAttributeQuotes: true //去除屬性 標簽的 引號 例如 <p id="test" /> 輸出 <p id=test/>
}
})
4、修改package.json
的build命令為指定配置文件構建打包"build": "webpack --config build/webpack.config.js"
,然后再次執行npm run build
,這時候已經可以把html模板和打包后的資源插入到html模板,最后打包進dist目錄
抽取webpack配置文件
為了區分開發環境和生產環境,下面我們一步一步抽取wenpack公共配置
分別創建 utils.js ,webpack.base.config.js , webpack.dev.config.js , webpack.prod.config.js
在抽取webpack配置過程中,需要使用webpack-merge插件,安裝方式
npm install -D webpack-merge
這個插件是用來合并webpack配置的,可以對不同文件的webpack配置合并成一個完整的webpack配置。具體用法請看下面
utils.js是webpack配置用的工具方法
const path = require("path")
exports.resolve = function (dir) {
return path.resolve(__dirname, dir)
}
webpack.base.config.js 是webpack在不同環境的公共配置
const utils = require("./utils")
module.exports = {
// 入口
entry: {
app: "./src/index"
},
// 出口
output: {
path : utils.resolve("../dist"),
filename: "js/[name].[hash].js",
publicPath: "/" // 打包后的資源的訪問路徑前綴
},
// 模塊
module:{
},
}
webpack.dev.config.js 是項目開發環境的配置
const webpackMerge = require("webpack-merge");
const baseWebpackConfig = require("./webpack.base.config")
const utils = require("./utils")
const HtmlWebpackPlugin = require("html-webpack-plugin")
module.exports = webpackMerge(baseWebpackConfig,{
// 指定構建環境
mode:"development",
// 插件
plugins:[
new HtmlWebpackPlugin({
filename: utils.resolve('./../dist/index.html'), // html模板的生成路徑
template: 'index.html',//html模板
inject: true, // true:默認值,script標簽位于html文件的 body 底部
})
],
// 開發環境本地啟動的服務配置
devServer: {
}
});
webpack.prod.config.js 是項目生產環境環境的配置
const webpackMerge = require("webpack-merge");
const baseWebpackConfig = require("./webpack.base.config")
const utils = require("./utils")
const HtmlWebpackPlugin = require("html-webpack-plugin")
module.exports = webpackMerge(baseWebpackConfig,{
// 指定構建環境
mode:"production",
// 插件
plugins:[
new HtmlWebpackPlugin({
filename: utils.resolve('./../dist/index.html'), // html模板的生成路徑
template: 'index.html',//html模板
inject: true, // true:默認值,script標簽位于html文件的 body 底部
hash: true, // 在打包的資源插入html會加上hash
// html 文件進行壓縮
minify: {
removeComments: true, //去注釋
collapseWhitespace: true, //壓縮空格
removeAttributeQuotes: true //去除屬性引用
}
})
],
})
在修改package.json
的build命令:
"build": "webpack --config build/webpack.prod.config.js"
然后再次執行npm run build
,一切正常!
配置生產環境webpack.dev.config.js其實上面步驟已經完成,但還比較簡單,后邊會結合react的打包進行整合
配置開發環境webpack.dev.config.js
開發環境需要我們使用webpack-dev-server插件,上邊已經安裝過
1、添加package.json命令,用webpack-dev-server啟動服務
"dev": "webpack-dev-server",
執行npm run dev
,現在已經可以正常啟動一個服務了,默認端口8080,服務的根目錄是項目的根目錄
但是這種方式沒有指定配置文件啟動,所以還需改成指定配置文件啟動
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.config.js",
在次執行npm run dev
,你會看到配置的資源和html模板已經被webpack構建
這時候瀏覽器打開http://localhost:8080,看到src/index.js的內容執行了
2、豐富webpack-dev-server配置,在webpack.dev.config.js的devServer屬性下添加開發環境啟
動服務的配置
// 開發環境本地啟動的服務配置
devServer: {
historyApiFallback: true, // 當找不到路徑的時候,默認加載index.html文件
hot: true,
contentBase: false, // 告訴服務器從哪里提供內容。只有在你想要提供靜態文件時才需要
compress: true, // 一切服務都啟用gzip 壓縮:
port: "8081", // 指定段靠譜
publicPath: "/", // 訪問資源加前綴
proxy: {
// 接口請求代理
},
}
執行npm run dev
,啟動服務,這時候配置文件已經把服務端口改為8081
,輸入http://localhost:8081,修改src/index.js,此時可以看到瀏覽器會熱更新,到此開發環境的配置基本完成,如果需要了解更多請查看文檔
引入react框架
安裝react
npm install -S react react-dom
修改src/index.js文件,使用react,react-dom
把react
的spa
頁面插入到html
模板id
為app
的盒子當中,重新運行項目npm run dev
,不出意外你驚訝的發現報錯了。這是此時webpack還不能編譯構建react的代碼,那么接下來我們進行支持react的打包構建
支持react的打包構建(配置webpack)
我們都知道,要想把react的代碼使用webpack編譯構建成瀏覽器可以運行的代碼,需要使用babel等工具進行"翻譯一下"
1、安裝,配置babel(babel7.x)
npm install -D @babel/core @babel/preset-env @babel/preset-react
npm install -D @babel/plugin-transform-runtime @babel/runtime @babel/runtime-corejs2
-
@babel/core babel
babel的核心庫 -
@babel/preset-env
把es6,es7語法轉換成es5。bebel7以上的版本只用這一個預設包就可以實現語法的轉換,已經廢棄了preset-stage-0,preset-stage-1,preset-stage-2
等這些包。但是這個包還不能轉換es6,es7的一些新特性比如Array.includes()
,這就需要我們使用@babel/plugin-transform-runtime
了 -
@babel/preset-react
把react語法轉換為es5 -
@babel/plugin-transform-runtime
支持一些es6,es7的新語法
那么安裝完了,我們需要添加babel的配置了,在項目目錄創建.babelrc
,配置內容如下
{
"presets": [
["@babel/preset-env", {
"modules": false,
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
}
}],
"@babel/preset-react"
],
"plugins": [
["@babel/plugin-transform-runtime",{
"corejs": 2, // polyfill 需要使用@babel/runtime-corejs2
"useBuildIns":"usage", //按需引入,即使用什么新特性打包什么新特性, 可以減小打包的體積
}]
]
}
上邊有兩個地方講解一下,在配置plugin-transform-runtime
時候,需要安裝依賴@babel/runtime
,還添加了特殊配置"corejs": 2
,"useBuildIns":"usage"
,為什么添加這些配置呢?
-
"corejs": 2
: @babel/runtime + @babel/plugin-transform-runtime 在 babel7 下只包含 helper function(即 Babel 進行處理時需要的幫助函數), 如果想實現 polyfill , 需要使用@babel/runtime-corejs2。 -
"useBuildIns":"usage"
: 要實現真正的按需引入,即使用什么新特性打包什么新特性,可以使用實驗性的 useBuildIns:"usage"。
2、webpack4.x配置編譯打包規則
安裝loaders
-
babel-loader
使用babel進行編譯項目
npm install -D babel-loader
-
style-loader,css-loader
編譯css文件
npm install -D style-loader css-loader
-
url-loader file-loader
引入文件路徑(圖片,字體)
npm install -D url-loader file-loader
-
less-loader
識別less
文件
npm install -D less less-loader
安裝完這些包之后,我們需要在webpacl.base.config.js添加打包編譯構建規則
在module下添加rules屬性
rules:[
{
test: /\.(js|jsx)$/,//一個匹配loaders所處理的文件的拓展名的正則表達式,這里用來匹配js和jsx文件(必須)
exclude: /node_modules/,//屏蔽不需要處理的文件(文件夾)(可選)
loader: 'babel-loader',//loader的名稱(必須)
},
{
test: /\.css$/,
use:[
{
loader: 'style-loader', // 創建 <style></style>
},
{
loader: 'css-loader', // 轉換css
}
]
},
{
test: /\.less$/,
use: [
{
loader: 'style-loader',
},
{
loader: 'css-loader',
},
{
loader: 'less-loader', // 編譯 Less -> CSS
},
],
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000, // url-loader 包含file-loader,這里不用file-loader, 小于10000B的圖片base64的方式引入,大于10000B的圖片以路徑的方式導入
name: 'static/img/[name].[hash:7].[ext]'
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000, // 小于10000B的圖片base64的方式引入,大于10000B的圖片以路徑的方式導入
name: 'static/fonts/[name].[hash:7].[ext]'
}
}
]
這些配置相比vue框架的配置少了對vue文件的編譯構建配置。你會發現在vue項目vue-loader,vue-style-loader,vue-template-compiler
這三個插件是必不可少的,這是用來處理vue文件的包
繼續在webpack.base.config.js添加
resolve: {
extensions: ['.js', '.json'], // 解析擴展。(當我們通過路導入文件,找不到改文件時,會嘗試加入這些后綴繼續尋找文件)
alias: {
'@': path.join(__dirname, '..', "src") // 在項目中使用@符號代替src路徑,導入文件路徑更方便
}
}
3、編寫頁面,運行項目,測試打包
新建assets/img目錄,把圖片放在該目錄下
在src
下新建home/index.js
,home/test.css
,home/test.less
home/index.js內容:
import React from 'react'
import "./test.less"
import "./test.css"
import buyImg from "@/assets/img/icon_buy_task.png"
import testImg from "@/assets/img/bg_store.png"
export default class Home extends React.Component {
render(){
return (
<div className="test test2">
<p>hello world</p>
<img src={buyImg} alt="" />
<img src={testImg} alt="" style={{width:360,height:60}}/>
</div>
)
}
}
test.css
.test2 {
font-size: 32px;
}
test.less
.test {
background: rebeccapurple;
}
然后修改src/index.js入口文件
import React from 'react'
import ReactDom from 'react-dom'
import HomePage from "./home"
class App extends React.Component {
render(){
return (
<div style={{color:"#333"}} className="test test2">
<HomePage />
</div>
)
}
}
ReactDom.render(<App/>,document.getElementById("app"))
這時候項目的基本雛形已經形成:
然后我們運行和打包項目
先執行npm run dev
,服務正常啟動,瀏覽器打開http://localhost:8081
頁面效果:
最后打包執行npm run build
,打包成功
此時,比較大的圖片和js的bundle都已經正常打包,那么我們怎么測試打包的代碼正常呢?這里我推薦一個插件(不用把靜態包部署到nginx服務器就可以運行)http-server
npm install -g http-server
全局安裝http-server包,安裝成功之后,cd dist
目錄,執行http-server
命令
這時候啟動了一個服務,默認開啟8080端口
如下圖:
這時候打開瀏覽器,輸入http://localhost:8081,發現頁面正常訪問!
就這樣一個基本的項目雛形有了!
下一篇: react技術棧的使用,react+webpack4搭建前端項目(二)react全家桶的使用