最近學習react.js,發現項目框架除了使用的js庫不一樣(vue.js、react.js),配置基本上是大同小異的css
進入根目錄,初始化項目html
cd reactProject
npm init -y // -y是採用默認配置
複製代碼
此時目錄出現package.json文件前端
在根目錄下新建src文件夾,在src下暫時新建名爲index的js文件做爲入口文件vue
根目錄下建立一個index.html,做爲入口頁面node
下載webpack時你可能會出現無限下載webpack-cli的問題,這是由於你沒有先全局安裝webpack和webpack-cli的緣由react
// webpack4.X開始webpack-cli被提出來做爲一個獨立的包了
// 在下載webpack同時也要下載webpack-cli,且必須同時下載不然會報錯,由於版本不匹配
cnpm install webpack-cli webpack --save-dev
複製代碼
webpack默認只能打包js模塊,它能夠將你寫的多個js模塊打包成一個js文件,最後在入口頁面引入它webpack
webpack4開始默認大於配置,換句話說能夠不用再引入一個配置文件來打包項目,所以他有不少默認值web
默認入口文件是src下的index.js,輸出爲dist目錄下的main.js(假如沒有dist目錄會自動建立)npm
可是它仍然是高配置的,假如須要咱們只需在項目根目錄下新建webpack.config.js來進行一切的配置json
相比於webpack4以前的版本,它的配置項多出一個mode選項,可選值爲"development" 或 "production"(默認),它們的區別就是development打包輸出的文件不是壓縮版本的
react和vue不一樣的是,react使用兩個包協同工做
cnpm install react react-dom --save-dev
複製代碼
index.js中
// index.js
import React from 'react'
// 這個包名必須這樣寫
import ReactDOM from 'react-dom'
/* *createElement: 建立虛擬dom元素 * 第一個參數爲標籤類型 * 第二個參數爲標籤屬性對象 * 剩餘參數皆爲參數爲子節點 */
const dom = React.createElement("h1",{id: "test"},"hello react")
// render函數是將虛擬dom插入目標容器Target container
ReactDOM.render(
dom,
document.getElementById("root")
)
複製代碼
index.html中
// index.html
<div id ="root"></div>
複製代碼
頁面中會看到hello react的字樣,審查元素以下
<div id="root"><h1 id="test">hello react</h1></div>
複製代碼
這說明咱們的準備工做都成功完成了
每次寫完新的內容要想看到效果,就必須使用webpack進行打包,咱們更但願當代碼改變時自動打包編譯
webpack-dev-server能夠幫咱們作到!
cnpm i webpack-dev-server --save-dev
複製代碼
咱們不能像使用webpack命令同樣使用webpack-dev-server命令,由於webpack-dev-server是局部安裝的,而令行裏只能使用全局安裝的包,使用局部安裝的包,咱們須要使用在package.json中配置scripts
// package.json
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "webpack-dev-server --hot"
},
複製代碼
而後再命令行使用npm run dev
npm run dev
複製代碼
注意看下面的節選的代碼
npm run dev
> vueproject@1.0.0 dev C:\myProject\reactProject
> webpack-dev-server
i 「wds」: Project is running at http://localhost:8080/
i 「wds」: webpack output is served from /
i 「wds」: Content not from webpack is served from C:\myProject\reactProject
i 「wdm」: Hash: e70fb3ae9bf074915cad
Version: webpack 4.35.0
複製代碼
從這裏咱們知道兩件事: 首先,咱們的項目運行在本機8080端口,其次webpack的output輸出在根目錄下,因此記得修改index.html中引入main.js的路徑,不然你是看不到新的效果的
可是咱們在根目錄下並無看到這個文件,這是由於它被放在內存中(這樣的讀寫速度快),而不是磁盤中,另外咱們還能夠修改端口,甚至能夠在編譯完成後自動打開瀏覽器
它具體的配置能夠是在webpack的devServer項
devServer:{
host: '127.0.0.1',
port: 8081,
open: true
}
複製代碼
也能夠是在cli裏,這是最暴力的方式,可是端口仍是放在devServer裏,方便之後項目的配置
// package.json
"scripts": {
"dev": "webpack-dev-server --open --port 30000"
},
複製代碼
既然將main.js放在內存中能夠加快讀寫速度,那是否是把頁面放在內存中能夠進一步加快讀寫速度了?
答案是確定的!使用html-webpack-plugin就能夠作到
cnpm i html-webpack-plugin --save-dev
複製代碼
// webpack.config.js
const htmlWebpackPlugin = require('html-webpack-plugin')
...
plugins: [
new htmlWebpackPlugin({
template: path.join(__dirname, "./index.html"),
filename: "index.html"
})
],
複製代碼
上面的代碼是根據磁盤中的index.html在內存中生成一個index.html,咱們在瀏覽器中審查頁面發現會多一個script標籤,這是插件自動將內存中的main.js加入到內存頁面中了,因此咱們這是應該刪除手動添加的script標籤
// index.html
<body>
<div id="app"></div>
<!--刪除或者註釋掉 <script src="./main.js"></script> -->
</body>
複製代碼
如今它已經能夠本身跑起來並自動監聽變化作出反應了
雖然開起來已經很完美了,可是像前面面那樣寫react虛擬dom老是以爲很複雜,做爲前端工程師,咱們更但願寫的dom就是這樣的,而後把它和以前同樣插入
const dom = <h1 id="test">hello react</h1>
ReactDOM.render(
dom,
document.getElementById("root")
)
複製代碼
這徹底是能夠的,上面的寫法就是react的擴展語法jsx,使用jsx語法必須使用babel-loader
有了前面文章的經驗,我發現若是如今下載babel-loader最好使用下面的形式,由於babel已經更新到7.x.x了,寫法和以前的版本有很大差別,不然老是會出現一些版本不兼容的錯誤
//下載loader加載器
cnpm i @babel/core babel-loader --save-dev
//下載插件
cnpm i @babel/plugin-transform-runtime --save-dev
//下載預設
cnpm i @babel/preset-env @babel/preset-react --save-dev
複製代碼
babel的兩種使用方法前面已經說過了,這裏再簡單的說說官網給出的別的簡單方法
第一種方法,在rules中配置babel-loader同時提供options選項
// 第一種寫法。
//除了基本的配置test外,可使用options,裏面必須有presets和plugins兩個選項
// presets是預設的babel語法轉換規則,這裏除了使用最新的規則外仍是用了針對react的jsx轉換規則
// plugins是指明使用的插件
module: {
rules: [
{
test: /\.js|jsx$/,
exclude: /node_modules/,
use: {
loader: "babel-loader",
options: {
presets: ["@babel/preset-env", "@babel/preset-react"],
plugins: ["@babel/plugin-transform-runtime"]
}
}
}
]
},
複製代碼
第二種方法根目錄新建.babelrc文件,格式同json
{
presets: ["@babel/preset-env", "@babel/preset-react"],
plugins: ["@babel/plugin-transform-runtime"]
}
//它會自動識別到這個文件
//此時能夠刪掉第一種方法中的options選項
複製代碼
第三種方法在package.json中添加babel節點
{
"name": "my-package",
"version": "1.0.0",
"babel": {
"presets": ["@babel/preset-env", "@babel/preset-react"],
"plugins": ["@babel/plugin-transform-runtime"]
}
}
複製代碼
第四種方法是根目錄新建.babelrc.js 配置和前面都同樣,只是可用js編寫
const presets = ["@babel/preset-env", "@babel/preset-react"];
const plugins = ["@babel/plugin-transform-runtime"];
// 這種寫法的好處是你能夠調用node API
if (process.env["ENV"] === "prod") {
plugins.push(...);
}
module.exports = { presets, plugins };
複製代碼
固然還有cli方法,或者選擇轉換node_modules目錄的babel.confog.js的方法,但都是比較複雜或者冷門的
在src下新建了一個css樣式表文件夾,裏面寫了本身針對本身組件的樣式,而後在須要的jsx文件中引入它,像我這樣
/* css/index.css文件 */
.test{
color: green
}
複製代碼
//在index.jsx文件中引入樣式
import React from "react";
import "@/css/index.css"
export default function Index() {
return <div className="test" id="index">index page</div>;
}
//在login.jsx中不引入樣式,可是添加class
import React from "react";
export default class Login extends React.Component {
render() {
// 由於class是js的關鍵字,因此jsx中使用className做爲html的class
return <div className="test">login page</div>;
}
}
複製代碼
這時候會報錯,提示使用合適的loader
和vue同樣要使用樣式表必須使用loader,由於它們都是jsx語法生成虛擬dom的,而jsx沒法解析樣式表
cnpm i style-loader css-loader --save-dev
複製代碼
下載完以後和vue項目同樣配置文件
rules: [
...
{
test: /\.css$/,
use: ["style-loader","css-loader"]
}
]
複製代碼
雖然這時候可使用樣式了可是,你會發現你沒有引入樣式的login組件頁面也是綠色字體了
好在css-loader能夠提供模塊化功能,咱們只需以下改動
rules: [
...
{
test: /\.css$/,
// 這種寫法和url帶參數很相似,這是開啓模塊化的意思
use: ["style-loader","css-loader?modules"]
}
]
複製代碼
此時咱們的引入css樣式須要一個參數去接收css暴露出來的模塊(固然這是css-loader的功能)
//在index.jsx文件中引入樣式
import React from "react";
import indxCss from "@/css/index.css"
console.log(indxCss) // => {test: "q7KCiLIWvHKVJp6HMfV2y"}
export default function Index() {
return <div className={indxCss.test} id="index">index page</div>;
}
複製代碼
同時說個有意思的事,css-loader除了modules參數外,還有不少參數 若是你不喜歡隨機的字符串作樣式的標識,能夠設置localIdentName參數,它是如下方式的組合
rules: [
...
{
test: /\.css$/i,
// 下面這種寫法是老版本的寫法,會一直報錯無效的版本,別問我是怎麼知道的,webpack官網沒有提示
//use: ["style-loader","css-loader?modules"],
// 新版本3.0.0是這樣的
// 去css-loader的npm官網才能看到這種寫法
use: [
{ loader: "style-loader" },
{
loader: "css-loader",
options: {
modules: {
localIdentName: "[path][name]-[local]-[hash:base64:5]"
}
}
}
]
}
]
複製代碼
雖然如今看上去是完美的,可是有個問題是假如如今引入第三方庫,它也是css文件,也會被模塊化的,但咱們但願它是全局有效的,比較好的作法就是第三方庫採用css樣式,而本身的樣式啓用scss或者less,因此你得安裝它們的loader
cnpm i less-loader --save-dev
複製代碼
添加loader
rules: [
...
{
test: /\.css$/,
use: ["style-loader", "css-loader"]
},
{
test: /\.less$/i,
use: [
{ loader: "style-loader" },
{
loader: "css-loader",
options: {
modules: {
localIdentName: "[path][name]-[local]-[hash:base64:5]"
}
}
},
{loader: "less-loader"}
]
}
]
複製代碼
若是在樣式中添加以下樣式
.test{
background-image: url(../imgs/11.jpg)
}
複製代碼
會發現jsx也沒法處理圖片url的,因此得添加loader去處理這些
url-loader內部使用了file-loader,因此兩個loader要同時下載
cnpm i url-loader file-loader --save-dev
複製代碼
基本的使用以下
module: {
rules: [
...
{
test: /\.(png|jpe?g|gif|svg|eot|ttf|woff|woff2)$/,
loader: "url-loader"
}
]
},
複製代碼
這個和css-loader設置同樣
module: {
rules: [
{
test: /\.(jpg|png|jpeg)$/,
loader: "url-loader",
options: {
limit: 8000, // 當文件字節大小超過限定值時觸發後面的設置
name: "[hash:8]-[name].[ext]" // 這是在原先的名稱和後綴名前加了八位的哈希碼
}
}
]
},
複製代碼
目前基本的功能都有了,可是仍是不夠完美,下期將會引入react-router,對業務進行封裝。從目前來看,無論vue項目框架仍是react框架,有極大的類似之處,學了vue學react就簡單多了,並且這是學習react對vue的理解也上升了一個層次。
若是你也作到這裏相信你也會有這種感覺
努力、奮鬥