开发完毕后就要编译上线了,因为编译和开发的构建部分基本上是一致的,只需要注意几个编译上线的而外差异,比如不需要开发服务,代码构建压缩,产物使用想对路径等。
增加 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],
});
}
值得注意的是我们开发的时候,需要监听文件变化重启开发服务,但是在编译的时候,我们不需要了,所以关于 rebuild
和 watch
相关的逻辑,我们都可以不执行。
修改 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),突然觉得用它来支撑一些运营活动页还挺合适的。
感谢阅读,如果看完今天的内容,你有一种 “就这” 的感觉,说明你变强了。