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é)點(diǎn)
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 中,
   * 而是在運(yùn)行時(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:上面的步驟,其實(shí)和我們創(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組件化的時候,其實(shí)不需要打包;只要使用 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)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容