IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 实验分析React编译产物 -> 正文阅读

[JavaScript知识库]实验分析React编译产物

webpack 帮我们处理了组件引用关系,将 jsx 转换成了 js 代码,这里我们通过实验看一下产物的跟预想的是否一样:

  1. 公共组件编译后是一份产物么?
  2. 能否手动控制公共组件一份还是多份产物?
  3. 如果使用 JSON 映射组件的方式,json 本身是否会打包进去?json 中未使用的组件是否会打包进去?

一、公共组件的编译结果

1.1 创建 CRA 项目

$ npx create-react-app cra-app
$ cd cra-app
$ npm start

1.2 引入 react-router-dom

$ npm i react-router-dom@5.3.0 -S

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';

ReactDOM.render(
  <App />,
  document.getElementById('root')
);

1.3 拆分子页面

App.js

import React from "react";
import {
  BrowserRouter as Router,
  Switch,
  Route,
  Link
} from "react-router-dom";
import Home from "./pages/home/index.tsx";
import About from "./pages/about/index.tsx";
import Dashboard from "./pages/dashboard/index.tsx";

export default function BasicExample() {
  return (
    <Router>
      <div>
        <ul>
          <li><Link to="/">Home</Link></li>
          <li><Link to="/about">About</Link></li>
          <li><Link to="/dashboard">Dashboard</Link> </li>
        </ul>
        <hr />
        <Switch>
          <Route exact path="/"><Home /></Route>
          <Route path="/about"><About /></Route>
          <Route path="/dashboard"><Dashboard /></Route>
        </Switch>
      </div>
    </Router>
  );
}

1.4 创建公共组件

Header.tsx

import React from "react";

const Header = () => {
  return <div>
    <h2>
      TheHeader
    </h2>
  </div>;
}

export default Header;

1.5 运行效果

在这里插入图片描述

1.6 打包产物

$ npm run build

在这里插入图片描述
因为还没有配置拆包以及懒加载,所以打包产物只有 main.jsmain.css,我们看通过分析编译产物得出以下结论:

  • TheHeader 只有 1 处,因此公共组件的产物只有 1 个
  • 3 个页面生成了 3 个函数,引用相同的公共组件

在这里插入图片描述

二、懒加载的编译产物

2.1 路由改为懒加载

App.js 使用 lazySuspense 改造

import React, {lazy, Suspense} from "react";
import {
  BrowserRouter as Router,
  Switch,
  Route,
  Link
} from "react-router-dom";
const Home = lazy(() => import("./pages/home/index.tsx"));
const About = lazy(() => import("./pages/about/index.tsx"));
const Dashboard = lazy(() => import("./pages/dashboard/index.tsx"));

export default function BasicExample() {
  return (
    <Router>
      <div>
        <ul>
          <li><Link to="/">Home</Link></li>
          <li><Link to="/about">About</Link></li>
          <li><Link to="/dashboard">Dashboard</Link> </li>
        </ul>
        <hr />
        <Suspense>
          <Switch>
	        <Route exact path="/"><Home /></Route>
	        <Route path="/about"><About /></Route>
	        <Route path="/dashboard"><Dashboard /></Route>
          </Switch>
        </Suspense>
      </div>
    </Router>
  );
}

2.2 打包产物

$ npm run build

可以看到多了 3 个 chunk.js 文件,对应 3 个页面
在这里插入图片描述
查看 3 个文件发现均有 TheHeader 公共组件

  • chunk 文件 1
    在这里插入图片描述
  • chunk 文件 2
    在这里插入图片描述
  • chunk 文件 3
    在这里插入图片描述
  • main.js 没有公共组件信息

结论: 懒加载会将公共组件编译进每个子页面,当然也可以通过 splitChunk 拆包的方式将公共组件打到同一处

2.3 合并懒加载页面

App.js 中将子页面设置为相同的 webpackChunkName

const Home = lazy(() => import(/* webpackChunkName:"ChildPage" */"./pages/home/index.tsx"));
const About = lazy(() => import(/* webpackChunkName:"ChildPage" */"./pages/about/index.tsx"));
const Dashboard = lazy(() => import(/* webpackChunkName:"ChildPage" */"./pages/dashboard/index.tsx"));

打包产物
在这里插入图片描述
此时公共组件只存在于 ChildPage.chunk.js
在这里插入图片描述

三、JSON 映射组件

3.1 新增 JSON 渲染组件

Wrapper/index.tsx 纯映射 HTML 元素

import React from "react";

/**
 * schema 容器
 * @param props 
 */
const Wrapper = (props) => {
  const {schema} = props;

  const elementTypeMap = ({type, inner}) => {
    let res;
    switch (type) {
      case 'div':
        res = <div>{inner}</div>
        break;
      case 'h1':
        res = <h1>{inner}</h1>
        break;
      case 'p':
        res = <p>{inner}</p>
        break;
      case 'span':
        res = <span>{inner}</span>
        break;
      case 'abcde': res = <>{inner}</>; break;
      default: res = <>{inner}</>
        break;
    }
    return res;
  }
  return elementTypeMap(schema);
}

export default Wrapper;

Header/index.tsx 中引用 Wrapper 组件

import React from "react";
import Wrapper from "../wrapper/index.tsx";

const Header = () => {
  return <div>
    <h2>
      TheHeader
    </h2>
    <Wrapper schema={{type: 'h1', inner: 'WrapperH1Test'}}/>
  </div>;
}

export default Header;

3.2 运行效果

根据 Headerschema 内容正常渲染 h1 标签
在这里插入图片描述

3.3 打包产物

看产物大小变化 Wrapper 组件应该编译进了 ChildPage.chunk.js
在这里插入图片描述
看到 header 组件中的 schema 并未编译
在这里插入图片描述
Wrapper 组件编译结果仅仅是将最后一个 case 和 default 进行了合并
在这里插入图片描述

结论: Wrapper 组件会被单独打包,所以其中引用的组件也会被打包,除非组件将未使用的 schema 类型去掉

四、JSON 渲染多级结构

4.1 修改 JSON 渲染组件

  • Wrapper/index.tsx 改为递归渲染
import React from "react";
/**
 * schema 容器
 * @param props 
 */
const Wraper = (props) => {
  const { schema } = props;

  const elementTypeMap = (type, inner) => {
    let res;
    switch (type) {
      case 'div':
        res = <div>{inner}</div>
        break;
      case 'h1':
        res = <h1>{inner}</h1>
        break;
      case 'p':
        res = <p>{inner}</p>
        break;
      case 'span':
        res = <span>{inner}</span>
        break;

      case 'abcde': res = <>{inner}</>; break;

      default: res = <>{inner}</>
        break;
    }
    return res;
  }

  const renderElement = ({ type, children, content }) => {
    return <>
      {elementTypeMap(type, <>
        {content}
        {children && children.map(item => renderElement(item))}
      </>)}
    </>;
  }
  return renderElement(schema);
}
export default Wraper;
  • About/index.tsx 页面渲染多层 JSON
import React from "react";
import Header from '../../components/header/index.tsx';
import Wraper from "../../components/wrapper/index.tsx";
const About =  () => {
  const schema = {
    type: 'div',
    children:
      [
        {
          type: 'h1',
          children: [
            { type: 'text', content: 'Header1' },
            { type: 'text', content: 'Header2' }
          ]
        },
        {
          type: 'div',
          children: [
            {
              type: 'p',
              content: 'p1',
              children: [
                { type: 'span', content: 'span1' }
              ]
            }
          ]
        },
        { 
          type: 'abcde', 
          content: 'abcdeContent',
        }
      ]
  };
  return (
    <div>
      <Header /> 
      <h2>About</h2>
      <Wraper schema={schema} />
    </div>
  );
}
export default About;

4.2 运行效果

在这里插入图片描述

4.3 打包产物

  • App.js 将 3 个页面编译到 2 个 chunk 文件中
const Home = lazy(() => import(/* webpackChunkName:"ChildPage1" */"./pages/home/index.tsx"));
const About = lazy(() => import(/* webpackChunkName:"ChildPage2" */"./pages/about/index.tsx"));
const Dashboard = lazy(() => import(/* webpackChunkName:"ChildPage2" */"./pages/dashboard/index.tsx"));

在这里插入图片描述

  • 根据产物大小判断应该是 ChildPage1.chunk.js 增加了新的 Wrapper 组件代码,ChildPage2.chunk.js 新增了 Wrapper 组件代码和 JSON 文件

  • ChildPage1.chunk.js
    在这里插入图片描述

  • ChildPage2.chunk.js
    在这里插入图片描述

  • 结果跟预期一致

五、渲染组件多环境打包

5.1 添加编译环境变量

  • package.json 中添加 REACT_APP_ENV 参数
  "scripts": {
    "start": "REACT_APP_ENV='web' react-scripts start",
    "build": "REACT_APP_ENV='web' react-scripts build",
    "build:mobile": "REACT_APP_ENV='mobile' react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  }
  • header/index.tsx 中展示环境变量
import React from "react";
import Wrapper from "../wrapper/index.tsx";

const Header = () => {
  return <div>
    <h2>
      TheHeader
    </h2>
    <p>ENV: {process.env.REACT_APP_ENV}</p>
    <Wrapper schema={{type: 'h1', inner: 'WrapperH1Test'}}/>
  </div>;
}
export default Header;
  • wrapper/index.tsx 中区分环境,从而区分引入组件
import React from "react";
/**
 * schema 容器
 * @param props 
 */
const Wrapper = (props) => {
  const { schema } = props;

  const elementTypeMap = (type, inner) => {
    let res;
    if(process.env.REACT_APP_ENV === 'web'){
      switch (type) {
        case 'div':
          res = <div>{inner}</div>
          break;
        case 'h1':
          res = <h1>{inner}</h1>
          break;
        case 'p':
          res = <p>{inner}</p>
          break;
        case 'span':
          res = <span>{inner}</span>
          break;
  
        case 'abcde': res = <>{inner}</>; break;
  
        default: res = <>{inner}</>
          break;
      }
    } else {
      switch (type) {
        case 'div':
          res = <div>{inner}</div>
          break;
        case 'h1':
          res = <h2>{inner}</h2>
          break;
        case 'p':
          res = <text>{inner}</text>
          break;
  
        default: res = <>{inner}</>
          break;
      }
    }
    return res;
  }

  const renderElement = ({ type, children, content }) => {
    return <>
      {elementTypeMap(type, <>
        {content}
        {children && children.map(item => renderElement(item))}
      </>)}
    </>;
  }
  return renderElement(schema);
}
export default Wrapper;

5.2 运行效果

在这里插入图片描述

5.3 打包产物

  • 打包 mobile
    在这里插入图片描述

  • ChildPage1.chunk.js 中的 Wrapper 组件
    在这里插入图片描述

结论: 可以看出 switch 语句前并没有环境变量的判断,也就是说属于 web 端的组件并没有打包进来,span 作为一个组件就没有找到

  • 打包 web
    在这里插入图片描述

  • ChildPage1.chunk.js 中的 Wrapper 组件
    在这里插入图片描述

结论: 只打包了 web 端组件,text 作为移动端特有组件没有找到

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-11-05 00:19:49  更:2022-11-05 00:20:49 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/17 20:15:25-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码