挑战21天手写前端框架 day21 什么?一个上线的 React 项目只有 100+KB?

简介: 挑战21天手写前端框架 day21 什么?一个上线的 React 项目只有 100+KB?

image.png

开发完毕后就要编译上线了,因为编译和开发的构建部分基本上是一致的,只需要注意几个编译上线的而外差异,比如不需要开发服务,代码构建压缩,产物使用想对路径等。


增加 malita build

program.command('build').description('框架构建命令').action(function() {
    const {
        build
    } = require('../lib/build');
    build();
});
复制代码


新建 packages/malita/src/build.ts

import { build as esbuild } from 'esbuild';
import { DEFAULT_PLATFORM } from './constants';
import { style } from './styles';
import { getAppData } from './appData';
import { getUserConfig } from './config';
import { getRoutes } from './routes';
import { generateEntry } from './entry';
import { generateHtml } from './html';
export const build = async () => {
    const cwd = process.cwd();
    // 生命周期
    // 获取项目元信息 
    const appData = await getAppData({
        cwd
    });
    // 获取用户数据
    const userConfig = await getUserConfig({
        appData, isProduction: true
    });
    // 获取 routes 配置
    const routes = await getRoutes({ appData });
    // 生成项目主入口
    await generateEntry({ appData, routes, userConfig });
    // 生成 Html
    await generateHtml({ appData, userConfig, isProduction: true });
    // 执行构建
    await esbuild({
        format: 'iife',
        logLevel: 'error',
        outdir: appData.paths.absOutputPath,
        platform: DEFAULT_PLATFORM,
        bundle: true,
        minify: true,
        define: {
            'process.env.NODE_ENV': JSON.stringify('production'),
        },
        external: ['esbuild'],
        plugins: [style()],
        entryPoints: [appData.paths.absEntryPath],
    });
}
复制代码

值得注意的是我们开发的时候,需要监听文件变化重启开发服务,但是在编译的时候,我们不需要了,所以关于 rebuildwatch 相关的逻辑,我们都可以不执行。


修改 getUserConfig

getUserConfig 中我们使用 isProduction: true 来进行逻辑的区分。

await build({
    format: 'cjs',
    logLevel: 'error',
    outdir: appData.paths.absOutputPath,
    bundle: true,
    watch: isProduction ? false : {
        onRebuild: (err, res) => {
            if (err) {
                console.error(JSON.stringify(err));
                return;
            }
            malitaServe?.emit('REBUILD', { appData });
        }
    },
    define: {
        'process.env.NODE_ENV': JSON.stringify(isProduction ? 'production' : 'development'),
    },
    external: ['esbuild'],
    entryPoints: [configFile],
});
复制代码


html 生成

在开发服务的时候,我们生成 html 的时候,js 文件的引用是采用前缀匹配走静态资源服务。但是在构建的时候,我们的静态资源会被写到和 html 的相对路径下的文件夹(或者同一个文件夹)。

// <script src="/${DEFAULT_OUTDIR}/${DEFAULT_FRAMEWORK_NAME}.js"></script>
// <script src="/malita/client.js"></script>
<script src="${isProduction ? '.' : `/${DEFAULT_OUTDIR}`}/${DEFAULT_FRAMEWORK_NAME}.js"></script>
${isProduction ? '' : '<script src="/malita/client.js"></script>'}
复制代码

注意修改构建产物可以执行压缩操作,经一步的降低产物包的大小 minify: true,


运行验证

修改 app 的 build 命令

"scripts": {
        "build": "malita build",
        "dev": "malita dev",
        "g": "malita g",
        "serve": "cd dist && serve"
    },
复制代码


执行构建

cd examples/app
pnpm build
复制代码

生成 examples/app/dist,查看产物大小 300KB,服务端开启 gzip 的话,在100KB 左右。


模拟上线

cd examples/app/dist
npx serve
复制代码

tips: npx 会找你当前包里面的命令,如果找不到会帮你装这个命令。

➜  dist git:(master) ✗ npx serve
   ┌──────────────────────────────────────────────────┐
   │                                                  │
   │   Serving!                                       │
   │                                                  │
   │   - Local:            http://localhost:3000      │
   │   - On Your Network:  http://10.128.5.188:3000   │
   │                                                  │
   │   Copied local address to clipboard!             │
   │                                                  │
   └──────────────────────────────────────────────────┘
复制代码

用浏览器访问 http://localhost:3000 项目功能一切正常。


malita 框架发布

$ pnpm build
> @ build /Users/congxiaochen/Documents/malita
> pnpm -r --filter ./packages run build
Scope: 2 of 4 workspace projects
packages/malita build$ pnpm esbuild ./src/** --bundle --outdir=lib --platform=node --external:esbuild --loader:
[11 lines collapsed]
│   lib/server.js                85.5kb
│   lib/mock.js                  75.6kb
│   lib/config.js                 3.3kb
│   lib/hd.js                     2.8kb
│   lib/routes.js                 2.7kb
│   lib/html.js                   2.7kb
│   lib/appData.js                2.4kb
│   lib/constants.js              2.0kb
│   lib/index.js                   46b 
│ ⚡ Done in 790ms
└─ Done in 1.6s
packages/keepalive build$ tsc
└─ Done in 1.2s
$ cd packages/malita
$ npm publish
npm notice 📦  malita@0.0.5
npm notice === Tarball Details === 
npm notice name:          malita                                  
npm notice version:       0.0.5                                   
npm notice filename:      malita-0.0.5.tgz                        
npm notice package size:  12.6 MB                                 
npm notice unpacked size: 71.7 MB                                 
npm notice shasum:        6263479592f41475b844bfcac60cced2fb3b7f11
npm notice integrity:     sha512-lRD6fbMjEtLY5[...]HRqMMWDy6VYTQ==
npm notice total files:   102                                     
npm notice 
+ malita@0.0.5
复制代码


这个框架的产物还真的挺小的(捂脸,一个 alita 项目产物最小也要快 1M),突然觉得用它来支撑一些运营活动页还挺合适的。


感谢阅读,如果看完今天的内容,你有一种 “就这” 的感觉,说明你变强了。


源码归档

目录
相关文章
|
12天前
|
前端开发 JavaScript 开发者
颠覆传统:React框架如何引领前端开发的革命性变革
【10月更文挑战第32天】本文以问答形式探讨了React框架的特性和应用。React是一款由Facebook推出的JavaScript库,以其虚拟DOM机制和组件化设计,成为构建高性能单页面应用的理想选择。文章介绍了如何开始一个React项目、组件化思想的体现、性能优化方法、表单处理及路由实现等内容,帮助开发者更好地理解和使用React。
41 9
|
14天前
|
前端开发 Unix 测试技术
揭秘!前端大牛们如何高效管理项目,确保按时交付高质量作品!
【10月更文挑战第30天】前端开发项目涉及从需求分析到最终交付的多个环节。本文解答了如何制定合理项目计划、提高团队协作效率、确保代码质量和应对项目风险等问题,帮助你学习前端大牛们的项目管理技巧,确保按时交付高质量的作品。
28 2
|
17天前
|
前端开发 JavaScript Android开发
前端框架趋势:React Native在跨平台开发中的优势与挑战
【10月更文挑战第27天】React Native 是跨平台开发领域的佼佼者,凭借其独特的跨平台能力和高效的开发体验,成为许多开发者的首选。本文探讨了 React Native 的优势与挑战,包括跨平台开发能力、原生组件渲染、性能优化及调试复杂性等问题,并通过代码示例展示了其实际应用。
45 2
|
19天前
|
前端开发 JavaScript 开发者
React与Vue:前端框架的巅峰对决与选择策略
【10月更文挑战第23天】React与Vue:前端框架的巅峰对决与选择策略
|
19天前
|
前端开发 JavaScript 开发者
“揭秘React Hooks的神秘面纱:如何掌握这些改变游戏规则的超能力以打造无敌前端应用”
【10月更文挑战第25天】React Hooks 自 2018 年推出以来,已成为 React 功能组件的重要组成部分。本文全面解析了 React Hooks 的核心概念,包括 `useState` 和 `useEffect` 的使用方法,并提供了最佳实践,如避免过度使用 Hooks、保持 Hooks 调用顺序一致、使用 `useReducer` 管理复杂状态逻辑、自定义 Hooks 封装复用逻辑等,帮助开发者更高效地使用 Hooks,构建健壮且易于维护的 React 应用。
28 2
|
19天前
|
前端开发 JavaScript 数据管理
React与Vue:两大前端框架的较量与选择策略
【10月更文挑战第23天】React与Vue:两大前端框架的较量与选择策略
|
18天前
|
前端开发 Android开发 开发者
前端框架趋势:React Native在跨平台开发中的优势与挑战
【10月更文挑战第26天】近年来,React Native凭借其跨平台开发能力在移动应用开发领域迅速崛起。本文将探讨React Native的优势与挑战,并通过示例代码展示其应用实践。React Native允许开发者使用同一套代码库同时构建iOS和Android应用,提高开发效率,降低维护成本。它具备接近原生应用的性能和用户体验,但也面临平台差异、原生功能支持和第三方库兼容性等挑战。
28 0
|
前端开发 JavaScript 中间件
react前端框架dva(四)
这篇文档梳理了基于 dva-cli 使用 dva 的最小知识集,让你可以用最少的时间掌握创建类似 dva-hackernews 的全部知识,并且不需要掌握额外的冗余知识。
2890 0
|
前端开发 API 测试技术
|
6月前
|
设计模式 前端开发 数据可视化
【第4期】一文了解React UI 组件库
【第4期】一文了解React UI 组件库
357 0