美文网首页
React 组件化之路1

React 组件化之路1

作者: 煎包小混沌 | 来源:发表于2020-04-19 19:57 被阅读0次
    一:废话不多说,直接干起来

    1:我们先创建一个react项目,使用最基础的方式创建,终端执行 npm init,按照提示,最后会创建一个 package.json 的文件

    npm init
    
    image.png

    2:添加必要的依赖库 cnpm install --save-dev @babel/core @babel/cli @babel/preset-env @babel/preset-react
    babel 用来将ES6 转换为 ES5,和转译 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

    执行完成后,我们的 package.json 的内容如下

    {
      "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"
      }
    }
    
    二:开始构建项目结构

    1:在当前目录下创建两个文件夹 publicsrc
    然后在 public 里创建 index.html 文件

    +-- public
    +-- src

    index.html 中的内容
    <!-- 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 下创建 index.js、App.js、App.css三个文件

    index.js 内容
    import React from "react";
    import ReactDOM from "react-dom";
    import App from "./App.js";
    
    ReactDOM.render(<App />, document.getElementById("root"));
    
    App.js 内容
    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 内容
    .App {
      margin: 1rem;
      font-family: Arial, Helvetica, sans-serif;
    }
    

    这时候的目录结构如下:

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

    三:添加打包的配置文件

    1:在根目录下创建webpack的配置文件,这里分开发环境的配置和发布环境的配置
    开发环境: webpack.dev.js

    开发环境:webpack.dev.js 内容 ,这个名称好像不能乱改,我直接写成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环境下的webpack配置文件,
    module.exports = {
      // 文件的入口
      entry: "./src/index.js",
      // 配置文件的名称
      mode: "development",
      // 指定打包的规则
      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 不会创建输入文件
      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()]
    };
    

    发布环境: webpack.prod.js

    const path = require('path');
    // 包含需要忽略绑定外部模块的节点
    const nodeExternals = require('webpack-node-externals');
    // 以下路径是从项目路径开始,非当前文件的相对路径
    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 中排除依赖」的方法。
       * 相反,所创建的 bundle 依赖于那些存在于用户环境(consumer's environment)中的依赖。
       * 此功能通常对 library 开发人员来说是最有用的,然而也会有各种各样的应用程序用到它。
       * 
       * 防止将某些 import 的包(package)打包到 bundle 中,
       * 而是在运行时(runtime)再去从外部获取这些扩展依赖(external dependencies)。
       * 例如:
       * externals: {
          jquery: 'jQuery'
        }
       */
      externals: [nodeExternals()]
    };
    

    此时的项目结构如下:


    image.png
    四:启动和打包

    1:在 package.json 中添加启动命令,执行 npm start启动项目

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

    2:执行 npm run build 将项目打包,此时会在项目根目录生成 dist 文件夹和xndex.js的文件,正常情况下,生成的文件就可以给其他人引用。

    五:组件化和引用

    1:上面的步骤,其实和我们创建一个 react 项目是一样的,主要是为了测试我们的组件,相当于组件的demo,我们用这个demo来调试我们的组件;但是我们的目的是将这个项目导出,所以需要修改一下 index.js 中的内容,导出这个组件

    index.js 修改如下,注意这里的导出方式为 export 并且修改了名称,引用的时候需要 import { Test1App } 需要加上括号哦。
    
    import App from "./App.js";
    export {
      App as Test1App
    }
    

    1:我们在使用react组件化的时候,其实不需要打包;只要使用 babel将src下面的文件进行ES6转ES5编译输出,我们添加另一个编译命令babel src --out-dir lib --copy-files(同时将不需要编译的文件copy出来),执行 npm run compile,然后在根目录下会生成 lib 文件夹
    添加启动命令

    package.json 添加内容如下:
    
    "scripts": {
        "start": "webpack-dev-server --config ./webpack.dev.js",
        "build": "webpack --config ./webpack.prod.js",
        "compile": "babel src --out-dir lib --copy-files"
      },
    

    2:执行上面的命令后,我们差不多完成了组件化,只需要在 package.json中修改 main 文件的入口即可

    package.json 添加内容如下:
    
    "main": "./lib/index.js",
    
    六:创建一个新的项目,引用组件

    1:我们创建另一个项目,这里我采用create-react-app这个工具链进行创建
    npx create-react-app my_firstcompent_exeple
    然后在项目里引用上面的组件 "myfirstcompent": "file:../myFirstCompent#v1.0.0"

    组件的名称,在组件的package.json 的name 中定义,#v1.0.0 是指定组件的版本,当我们修改组件后,要提高组件的版本,然后在依赖中修改引用组件的版本
    "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:执行 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

    相关文章

      网友评论

          本文标题:React 组件化之路1

          本文链接:https://www.haomeiwen.com/subject/oqiovhtx.html