開(kāi)始之前
在書(shū)寫(xiě)文章之前攀例,我假設(shè)大家已經(jīng)有了 JavaScript
减途,Node 包管理工具
噩峦,Linux 終端操作
這些基本技能秀睛,接下來(lái),我將一步一步指引大家從頭搭建一個(gè) React
項(xiàng)目
最終實(shí)現(xiàn)的效果
我們將使用 Webpack
和 Babel
搭建一個(gè) React
應(yīng)用坞靶,我們的目的很清晰憔狞,就是 更好的理解和掌握這些工具的使用
我們創(chuàng)建的應(yīng)用程序既要做到 最小
,也要遵循 最佳實(shí)踐
彰阴,為不是特別熟練的同學(xué)鞏固一下基礎(chǔ)
初始化
創(chuàng)建你的項(xiàng)目瘾敢,并添加的你的配置文件 package.json
mkdir webpack-babel-react-revisited
cd webpack-babel-react-revisited
yarn init
Webpack
我們首先安裝 Webpack
,它是目前非常流行的 模塊打包器
,它將應(yīng)用程序包含的每個(gè)模塊打包成少量的 塊
簇抵,以便這些代碼從服務(wù)器加載到瀏覽器中
yarn add webpack --dev
接下來(lái)庆杜,我們開(kāi)始書(shū)寫(xiě)一些模塊。我們將源文件 app.js
保存到 src
目錄中
/** app.js */
console.log('Hello from 楓上霧棋!');
然后正压,我們跑一下 Webpack
./node_modules/webpack/bin/webpack.js ./src/app.js --output-filename ./dist/app.bundle.js
如果你打開(kāi)生成的 app.bundle.js
,你會(huì)發(fā)現(xiàn)上面是 webpack
的模塊處理代碼责球,下面是我們書(shū)寫(xiě)的 console.log
這條指令是將我們的 app.js
作為 Webpack
的 入口文件
焦履,將結(jié)果輸出到 dist
文件夾中,指令有些冗長(zhǎng)雏逾,在實(shí)際開(kāi)發(fā)中嘉裤,我們使用 webpack
配置文件來(lái)代替,為了文檔結(jié)構(gòu)看起來(lái)更加清晰栖博,參考 目錄
如下
├── config
│ ├── paths.js
│ ├── webpack.config.prod.js
├── src
│ ├── app.js
├── package.json
下面是參考 配置
paths.js
const path = require('path');
const fs = require('fs');
const appDirectory = fs.realpathSync(process.cwd());
const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
module.exports = {
appDist: resolveApp('dist'),
appSrc: resolveApp('src'),
};
這個(gè)文件不是必須的屑宠,但在項(xiàng)目增大后,它的意義就瞬間出來(lái)了
webpack.config.prod.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const paths = require('./paths');
const plugins = [
new HtmlWebpackPlugin({
title: 'webpack babel react revisited',
filename: path.join(paths.appDist, 'index.html'),
}),
];
const config = {
entry: {
app: path.join(paths.appSrc, 'app'),
},
output: {
path: paths.appDist,
filename: 'assets/js/[name].js',
},
resolve: {
extensions: ['.js', '.jsx'],
},
plugins,
};
module.exports = config;
這里我們還添加了一個(gè) html-webpack-plugin仇让,它簡(jiǎn)化了我們 HTML
文件的創(chuàng)建典奉,安裝我們就不再這里贅述了,如果還不知道的同學(xué)可以點(diǎn)擊鏈接查看
其中丧叽,我們還使用了一個(gè) 語(yǔ)法糖
卫玖,這樣在我們導(dǎo)入 .js
,.jsx
時(shí)就不需要指定擴(kuò)展名了
接下來(lái)踊淳,我們指定配置文件再跑一下 Webpack
./node_modules/webpack/bin/webpack.js --config config/webpack.config.prod.js
發(fā)現(xiàn)除了實(shí)現(xiàn)上面的效果外假瞬,還自動(dòng)幫我們生成了一個(gè) index.html
,我們可以點(diǎn)擊這個(gè) html
迂尝,在控制臺(tái)中查看效果脱茉,相比上面,是不是方便了很多
當(dāng)然垄开,最后我們肯定也不是使用這種方式來(lái) build
琴许,打開(kāi) package.json
,添加如下 腳本命令
溉躲,然后執(zhí)行 yarn build
虚吟,是不是瞬間感覺(jué) nice
了很多
"scripts": {
"clean": "rimraf dist *.log .DS_Store",
"build": "yarn run clean && webpack --config config/webpack.config.prod.js --progress"
}
Webpack dev server
除此之外,Webpack
為我們提供了一個(gè)的 dev server
签财,它還支持 模塊熱替換
首先串慰,安裝 webpack-dev-server
yarn add --dev webpack-dev-server
在 config
目錄中添加配置文件 webpack.config.dev.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const OpenBrowserPlugin = require('open-browser-webpack-plugin');
const paths = require('./paths');
const hostname = process.env.HOST || 'localhost';
const port = process.env.PORT || 3000;
const plugins = [
new HtmlWebpackPlugin({
title: 'webpack babel react revisited',
filename: path.join(paths.appDist, 'index.html'),
}),
new OpenBrowserPlugin({ url: `http://${hostname}:${port}` }),
];
const config = {
entry: {
app: path.join(paths.appSrc, 'app'),
},
output: {
path: paths.appDist,
filename: 'assets/js/[name].js',
},
resolve: {
extensions: ['.js', '.jsx'],
},
plugins,
devServer: {
contentBase: paths.appDist,
compress: true,
port,
},
};
module.exports = config;
在 webpack.config.prod.js
的基礎(chǔ)上,我們?cè)黾恿?open-browser-webpack-plugin 插件和 devServer
配置唱蒸,open-browser-webpack-plugin
插件顧名思義邦鲫,會(huì)幫我們自動(dòng)打開(kāi) dev server
最后返回給我們的地址
更新 package.json
"scripts": {
"clean": "rimraf dist *.log .DS_Store",
"webpack:dev":
"NODE_ENV=development webpack-dev-server --config config/webpack.config.dev.js --progress",
"webpack:prod":
"NODE_ENV=production webpack --config config/webpack.config.prod.js --progress",
"start": "yarn run clean && yarn run webpack:dev",
"build": "yarn run clean && yarn run webpack:prod"
}
現(xiàn)在,我們就可以通過(guò)如下方式來(lái)啟動(dòng)
yarn start
啟動(dòng)后,有沒(méi)有瞬間感覺(jué)很棒
Babel
為了能夠使用 ES6
以及更高版本庆捺,我們需要一個(gè) 轉(zhuǎn)換編譯器
古今,我們選擇 Babel
,它能將 ES6
轉(zhuǎn)換成可以在瀏覽器中運(yùn)行的代碼滔以,除此之外捉腥,他還內(nèi)置了 React JSX
擴(kuò)展,可以說(shuō)它的出現(xiàn)推動(dòng)了 JavaScipt
的發(fā)展
所有你画,我們安裝下面這些依賴包
yarn add --dev babel-loader babel-core babel-preset-env babel-preset-react
創(chuàng)建 Babel
默認(rèn)配置文件 .babelrc
{
"presets": ["env", "react"]
}
這個(gè)是告訴 Babel
用我們剛剛安裝的兩個(gè) presets
接下來(lái)抵碟,更新 webpack
配置文件
config.module = {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: ['babel-loader'],
},
],
}
更新以后,雖然看不到什么變化坏匪,但事實(shí)上我們可以使用 ES6
了
React
最后拟逮,我們來(lái)添加 React
,這也可能是你閱讀這篇文章的原因
首先适滓,我們還是先安裝它
yarn add react react-dom
用下面代碼替換 console.log
import React, { Component } from 'react';
import { render } from 'react-dom';
export default class Hello extends Component {
render() {
return <h1>Hello from 楓上霧棋!</h1>;
}
}
render(<Hello />, document.getElementById('app'));
因?yàn)橐砑?<div id="app"></div>
敦迄,所以我們要修改一下 html-webpack-plugin
的配置
new HtmlWebpackPlugin({
template: path.join(paths.appSrc, 'index.html'),
}),
參考 template
如下
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>webpack babel react revisited</title>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="app"></div>
</body>
</html>
接下來(lái),就是見(jiàn)證奇跡的時(shí)刻
重新啟動(dòng)服務(wù)凭迹,你有沒(méi)有發(fā)現(xiàn)搭建一個(gè) React
應(yīng)用程序就這么簡(jiǎn)單
接下里罚屋,大家就可以 自行探索
,添加更多的東西來(lái)適應(yīng)自身應(yīng)用程序的需要
下面再補(bǔ)充一下如何添加 CSS
和 圖片
CSS
每個(gè) web 應(yīng)用程序都離不開(kāi) CSS
嗅绸,我們?cè)?src
目錄中創(chuàng)建 style.css
body,
html,
#app {
margin: 0;
width: 100%;
height: 100%;
}
#app {
padding: 30px;
font-family: '微軟雅黑';
}
將其添加到應(yīng)用程序中我們需要使用 css-loader
如果想將 css
注入 style
標(biāo)簽中沿后,我們還需要 style-loader,通常朽砰,是將這兩個(gè)結(jié)合使用
我們使用 extract-text-webpack-plugin 將其解壓到外部
為此尖滚,我們首先安裝
yarn add --dev css-loader style-loader extract-text-webpack-plugin
然后在 app.js
中導(dǎo)入 style.css
import './style.css';
最后更新 webpack
配置文件
config.module = {
rules: [
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: 'css-loader',
}),
},
],
}
config.plugins.push([
new ExtractTextPlugin("styles.css"),
])
看起來(lái)稍顯復(fù)雜,但是大功告成瞧柔,為了更好地使用它漆弄,我們都得經(jīng)歷這個(gè)過(guò)程
重新啟動(dòng)服務(wù),你會(huì)發(fā)現(xiàn)你的 dist
目錄中多了一個(gè) styles.css
圖片
最后我們?cè)黾?file-loader 來(lái)處理我們引入的圖片等文件
首先造锅,安裝 file-loader
yarn add --dev file-loader
我們?cè)?src/images
中放入一張圖片撼唾,在 app.js
中導(dǎo)入
import avatar from './images/avatar.jpg';
export default class Hello extends Component {
render() {
return (
<div>
<img src={avatar} alt="avatar" style={{ width: 400, height: 250 }} />
</div>
);
}
}
更新 webpack
配置文件
config.module = {
rules: [
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'assets/images/',
},
},
],
},
],
}
重啟服務(wù),哈哈
總結(jié)
如果有什么問(wèn)題哥蔚,可以查看 webpack-babel-react-revisited 倉(cāng)庫(kù)
現(xiàn)在倒谷,大家對(duì)搭建 React
應(yīng)用程序是不是感覺(jué)輕松了很多,但 React
整個(gè)技術(shù)棧并不止包括這些糙箍,還有 Redux
渤愁,React Router
,單元測(cè)試
深夯,代碼校驗(yàn)
等內(nèi)容抖格,關(guān)于 React
其他內(nèi)容诺苹,歡迎查看日志其他文章
原文鏈接:Setting up Webpack, Babel and React from scratch, revisited