挑战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),突然觉得用它来支撑一些运营活动页还挺合适的。


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


源码归档

目录
相关文章
|
8天前
|
开发框架 前端开发 JavaScript
探索前端开发中的跨平台框架React Native
本文将介绍前端开发中一种备受关注的跨平台框架React Native,通过比较原生应用与React Native的优缺点,探讨其在实际项目中的应用以及未来发展趋势。
|
2天前
|
JavaScript 前端开发
React与Vue性能对比:两大前端框架的性能
React与Vue性能对比:两大前端框架的性能
|
2天前
|
前端开发 JavaScript
前端框架React原理
前端框架React原理
9 0
|
6天前
|
存储 前端开发 JavaScript
【JavaEE初阶】 博客系统项目--前端页面设计实现
【JavaEE初阶】 博客系统项目--前端页面设计实现
|
7天前
|
存储 前端开发 JavaScript
探索前端框架React Hooks的魅力
【2月更文挑战第2天】本文深入探讨了前端框架React Hooks的核心概念及其在现代Web开发中的重要性,分析了Hooks相较于传统class组件的优势所在,展示了它带来的便利和灵活性,为开发者提供了更加高效和优雅的解决方案。
|
7天前
|
前端开发 JavaScript C++
探讨前端框架选择:React vs Angular vs Vue
【2月更文挑战第2天】 在当今快速发展的前端开发领域,选择合适的前端框架至关重要。本文将深入探讨三大热门前端框架:React、Angular和Vue,分析它们的特点、优势和劣势,帮助开发者更好地理解并选择适合自己项目的前端框架。
11 3
|
JSON 前端开发 数据处理
|
1月前
|
设计模式 前端开发 数据可视化
【第4期】一文了解React UI 组件库
【第4期】一文了解React UI 组件库
51 0

相关产品

  • 云迁移中心