React 組件化之路1

一:廢話不多說,直接干起來

1:我們先創(chuàng)建一個react項目,使用最基礎(chǔ)的方式創(chuàng)建牵寺,終端執(zhí)行 npm init械姻,按照提示妒蛇,最后會創(chuàng)建一個 package.json 的文件

npm init
image.png

2:添加必要的依賴庫 cnpm install --save-dev @babel/core @babel/cli @babel/preset-env @babel/preset-react
babel 用來將ES6 轉(zhuǎn)換為 ES5,和轉(zhuǎn)譯 react 代碼

2.1:添加webpack打包依賴 cnpm install --save-dev webpack webpack-cli webpack-dev-server webpack-node-external style-loader css-loader babel-loader

2.2:添加 react 依賴 install --save-dev react react-dom

執(zhí)行完成后楷拳,我們的 package.json 的內(nèi)容如下

{
  "name": "myfirstcompent",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@babel/cli": "^7.8.4",
    "@babel/core": "^7.9.0",
    "@babel/preset-env": "^7.9.5",
    "@babel/preset-react": "^7.9.4",
    "babel-loader": "^8.1.0",
    "css-loader": "^3.5.2",
    "react": "^16.13.1",
    "react-dom": "^16.13.1",
    "style-loader": "^1.1.4",
    "webpack": "^4.42.1",
    "webpack-cli": "^3.3.11",
    "webpack-dev-server": "^3.10.3",
    "webpack-node-externals": "^1.7.2"
  }
}
二:開始構(gòu)建項目結(jié)構(gòu)

1:在當(dāng)前目錄下創(chuàng)建兩個文件夾 publicsrc
然后在 public 里創(chuàng)建 index.html 文件

+-- public
+-- src

index.html 中的內(nèi)容
<!-- sourced from https://raw.githubusercontent.com/reactjs/reactjs.org/master/static/html/single-file-example.html -->
<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <title>React Starter</title>
</head>

<body>
  <div id="root"></div>
  <noscript>
    You need to enable JavaScript to run this app.
  </noscript>
  <script src="../dist/bundle.js"></script>
</body>

</html>

接著在 src 下創(chuàng)建 index.js绣夺、App.js、App.css三個文件

index.js 內(nèi)容
import React from "react";
import ReactDOM from "react-dom";
import App from "./App.js";

ReactDOM.render(<App />, document.getElementById("root"));
App.js 內(nèi)容
import React, { Component} from "react";
import "./App.css";

class App extends Component{
  render(){
    return(
      <div className="App">
        <h1> Hello, World! </h1>
      </div>
    );
  }
}

export default App;
App.css 內(nèi)容
.App {
  margin: 1rem;
  font-family: Arial, Helvetica, sans-serif;
}

這時候的目錄結(jié)構(gòu)如下:

+-- node_modules
+-- public
| +-- index.html
+-- src
| +-- App.css
| +-- App.js
| +-- index.js
+-- package.json

三:添加打包的配置文件

1:在根目錄下創(chuàng)建webpack的配置文件欢揖,這里分開發(fā)環(huán)境的配置和發(fā)布環(huán)境的配置
開發(fā)環(huán)境: webpack.dev.js

開發(fā)環(huán)境:webpack.dev.js 內(nèi)容 陶耍,這個名稱好像不能亂改,我直接寫成webpack.config.dev.js 一直報錯
-----------------------
RROR in ./src/index.js 5:16
Module parse failed: Unexpected token (5:16)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| import App from "./App.js";
| 
> ReactDOM.render(<App />, document.getElementById("root"));
---------------------

const path = require("path");
const webpack = require("webpack");
// dev環(huán)境下的webpack配置文件她混,
module.exports = {
  // 文件的入口
  entry: "./src/index.js",
  // 配置文件的名稱
  mode: "development",
  // 指定打包的規(guī)則
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        // 不包含 node_modules 中的文件
        exclude: /(node_modules|bower_components)/,
        // 解析 ES6 依賴
        loader: "babel-loader",
        // 解析 react 
        options: { presets: ["@babel/env", "@babel/preset-react"] }
      },
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"]
      }
    ]
  },
  resolve: { extensions: ["*", ".js", ".jsx"] },
  // 輸入路徑與文件烈钞,dev 不會創(chuàng)建輸入文件
  output: {
    path: path.resolve(__dirname, "./dist/"),
    publicPath: "./dist/",
    filename: "bundle.js"
  },
  // 指定 dev 的配置
  devServer: {
    contentBase: path.join(__dirname, "public/"),
    port: 3000,
    publicPath: "http://localhost:3000/dist/",
    hotOnly: true
  },
  // 增加 模塊熱替換插件
  plugins: [new webpack.HotModuleReplacementPlugin()]
};

發(fā)布環(huán)境: webpack.prod.js

const path = require('path');
// 包含需要忽略綁定外部模塊的節(jié)點
const nodeExternals = require('webpack-node-externals');
// 以下路徑是從項目路徑開始,非當(dāng)前文件的相對路徑
module.exports = {
  mode: "production",
  entry: "./src/index.js",
  // 輸入路徑和文件
  output: {
    filename: "xndex.js",
    path: path.resolve(__dirname, "./dist"),
    // ES6 的 export 
    libraryTarget: "commonjs2"
  },
  module: {
    rules: [
      {
        test: /\.(js|jsx)$/,
        exclude: /(node_modules|bower_components)/,
        loader: "babel-loader",
        options: { presets: ["@babel/env", "@babel/preset-react"] }
      },
      {
        test: /\.css$/,
        use: ['style-loader', 'css-loader']
      },
      {
        test: /\.cm\.styl$/,
        loader: 'style-loader!css-loader?modules&camelCase&localIdentName=[local]-[hash:base64:5]!stylus-loader'
      }
    ]
  },
  resolve: { extensions: ["*", ".js", ".jsx"] },
  /**
   * externals 配置選項提供了「從輸出的 bundle 中排除依賴」的方法产上。
   * 相反棵磷,所創(chuàng)建的 bundle 依賴于那些存在于用戶環(huán)境(consumer's environment)中的依賴。
   * 此功能通常對 library 開發(fā)人員來說是最有用的晋涣,然而也會有各種各樣的應(yīng)用程序用到它仪媒。
   * 
   * 防止將某些 import 的包(package)打包到 bundle 中,
   * 而是在運行時(runtime)再去從外部獲取這些擴(kuò)展依賴(external dependencies)谢鹊。
   * 例如:
   * externals: {
      jquery: 'jQuery'
    }
   */
  externals: [nodeExternals()]
};

此時的項目結(jié)構(gòu)如下:


image.png
四:啟動和打包

1:在 package.json 中添加啟動命令算吩,執(zhí)行 npm start啟動項目

"scripts": {
    "start": "webpack-dev-server --config ./webpack.dev.js",
    "build": "webpack --config ./webpack.prod.js"
  },

2:執(zhí)行 npm run build 將項目打包,此時會在項目根目錄生成 dist 文件夾和xndex.js的文件佃扼,正常情況下偎巢,生成的文件就可以給其他人引用。

五:組件化和引用

1:上面的步驟兼耀,其實和我們創(chuàng)建一個 react 項目是一樣的压昼,主要是為了測試我們的組件,相當(dāng)于組件的demo瘤运,我們用這個demo來調(diào)試我們的組件窍霞;但是我們的目的是將這個項目導(dǎo)出,所以需要修改一下 index.js 中的內(nèi)容拯坟,導(dǎo)出這個組件

index.js 修改如下但金,注意這里的導(dǎo)出方式為 export 并且修改了名稱,引用的時候需要 import { Test1App } 需要加上括號哦郁季。

import App from "./App.js";
export {
  App as Test1App
}

1:我們在使用react組件化的時候冷溃,其實不需要打包钱磅;只要使用 babel將src下面的文件進(jìn)行ES6轉(zhuǎn)ES5編譯輸出,我們添加另一個編譯命令babel src --out-dir lib --copy-files(同時將不需要編譯的文件copy出來)似枕,執(zhí)行 npm run compile盖淡,然后在根目錄下會生成 lib 文件夾
添加啟動命令

package.json 添加內(nèi)容如下:

"scripts": {
    "start": "webpack-dev-server --config ./webpack.dev.js",
    "build": "webpack --config ./webpack.prod.js",
    "compile": "babel src --out-dir lib --copy-files"
  },

2:執(zhí)行上面的命令后,我們差不多完成了組件化菠净,只需要在 package.json中修改 main 文件的入口即可

package.json 添加內(nèi)容如下:

"main": "./lib/index.js",
六:創(chuàng)建一個新的項目禁舷,引用組件

1:我們創(chuàng)建另一個項目,這里我采用create-react-app這個工具鏈進(jìn)行創(chuàng)建
npx create-react-app my_firstcompent_exeple
然后在項目里引用上面的組件 "myfirstcompent": "file:../myFirstCompent#v1.0.0"

組件的名稱毅往,在組件的package.json 的name 中定義牵咙,#v1.0.0 是指定組件的版本,當(dāng)我們修改組件后攀唯,要提高組件的版本洁桌,然后在依賴中修改引用組件的版本
"dependencies": {
    "@testing-library/jest-dom": "^4.2.4",
    "@testing-library/react": "^9.3.2",
    "@testing-library/user-event": "^7.1.2",
    "react": "^16.13.1",
    "react-dom": "^16.13.1",
    "react-scripts": "3.4.1",
    "myfirstcompent": "file:../myFirstCompent#v1.0.0"
  },

2:執(zhí)行 cnpm install ,我們可以看到終端顯示
? All packages installed (1 packages installed from local file, used 4s(network 4s), speed 0B/s, json 0(0B), tarball 0B)顯示我們引用了一個 本地的文件

3:在 index.js 文件中增加引用 import {Test1App} from 'myfirstcompent';

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
// import App from './App';
import {Test1App} from 'myfirstcompent';
import * as serviceWorker from './serviceWorker';

ReactDOM.render(
  <React.StrictMode>
    <Test1App />
  </React.StrictMode>,
  document.getElementById('root')
);

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
七:最后我們跑起來看看
image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末侯嘀,一起剝皮案震驚了整個濱河市另凌,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌戒幔,老刑警劉巖吠谢,帶你破解...
    沈念sama閱讀 221,888評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異诗茎,居然都是意外死亡工坊,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評論 3 399
  • 文/潘曉璐 我一進(jìn)店門敢订,熙熙樓的掌柜王于貴愁眉苦臉地迎上來王污,“玉大人,你說我怎么就攤上這事楚午≌哑耄” “怎么了?”我有些...
    開封第一講書人閱讀 168,386評論 0 360
  • 文/不壞的土叔 我叫張陵矾柜,是天一觀的道長阱驾。 經(jīng)常有香客問我,道長怪蔑,這世上最難降的妖魔是什么啊易? 我笑而不...
    開封第一講書人閱讀 59,726評論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮饮睬,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘篮奄。我一直安慰自己捆愁,他們只是感情好割去,可當(dāng)我...
    茶點故事閱讀 68,729評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著昼丑,像睡著了一般呻逆。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上菩帝,一...
    開封第一講書人閱讀 52,337評論 1 310
  • 那天咖城,我揣著相機(jī)與錄音,去河邊找鬼呼奢。 笑死宜雀,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的握础。 我是一名探鬼主播辐董,決...
    沈念sama閱讀 40,902評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼禀综!你這毒婦竟也來了简烘?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,807評論 0 276
  • 序言:老撾萬榮一對情侶失蹤定枷,失蹤者是張志新(化名)和其女友劉穎孤澎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體欠窒,經(jīng)...
    沈念sama閱讀 46,349評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡覆旭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,439評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了贱迟。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片姐扮。...
    茶點故事閱讀 40,567評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖衣吠,靈堂內(nèi)的尸體忽然破棺而出茶敏,到底是詐尸還是另有隱情,我是刑警寧澤缚俏,帶...
    沈念sama閱讀 36,242評論 5 350
  • 正文 年R本政府宣布惊搏,位于F島的核電站,受9級特大地震影響忧换,放射性物質(zhì)發(fā)生泄漏恬惯。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,933評論 3 334
  • 文/蒙蒙 一亚茬、第九天 我趴在偏房一處隱蔽的房頂上張望酪耳。 院中可真熱鬧,春花似錦、人聲如沸碗暗。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,420評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽言疗。三九已至晴圾,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間噪奄,已是汗流浹背死姚。 一陣腳步聲響...
    開封第一講書人閱讀 33,531評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留勤篮,地道東北人都毒。 一個月前我還...
    沈念sama閱讀 48,995評論 3 377
  • 正文 我出身青樓,卻偏偏與公主長得像叙谨,于是被迫代替她去往敵國和親温鸽。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,585評論 2 359

推薦閱讀更多精彩內(nèi)容