当前位置: 首页 > article >正文

如何模拟一个小程序项目打包的流程

一、Uni-app 执行 yarn run dev:mp-weixin后会发生什么

(一)准备工作

  1. 克隆项目:创建以 typescript 开发的工程(如命令行创建失败,请直接访问 https://gitee.com/dcloud/uni-preset-vue/repository/archive/vite-ts.zip 下载模板)。
    • npx degit dcloudio/uni-preset-vue#vite-ts my-vue3-project
  2. 执行 dev:mp-weixin这个命令时,yarnnpm会运行package.json文件中定义的scripts部分的对应命令。通常会类似于这样定义:
    "scripts": {
      "dev:mp-weixin": "uni -p mp-weixin" 
    }
    

(二)执行后发生的事情

  1. 编译项目uni -p mp-weixin命令会调用 uni-app 的 CLI 工具,编译你的项目代码。uni-app 会将你的 Vue.js 代码转换为微信小程序可以识别的代码,包括将 .vue文件编译成微信小程序的wxmlwxssjsjson文件。
  2. 生成微信小程序项目文件:编译完成后,uni-app 会在项目的dist目录下生成一个专门为微信小程序准备的项目文件夹。这个文件夹包含了所有编译好的代码和资源文件,可以直接在微信开发者工具中打开并运行。
  3. 监视文件变化(开发模式):如果命令是针对开发环境的(如dev:mp-weixin),uni-app CLI 通常会启动一个开发服务器,并持续监视项目文件的变化。当你修改项目中的文件时,它会自动重新编译,并更新到dist目录中的微信小程序项目文件夹中。
  4. 启动开发服务器:在某些情况下,uni-app 还可能会启动一个本地开发服务器,方便在浏览器中实时预览应用的 H5 版本,并且可以同步调试。

二、实现类似 uni 插件的 vite 插件

(一)创建命令行工具

  1. 在项目中创建一个可以在命令行执行的工具,通常可以通过在package.json中定义一个脚本来实现。可以使用 Node.js 创建一个 CLI 工具,并通过配置package.json来实现全局或本地运行。在package.json中定义vue-mini作为一个可执行命令,并且将bin/vue-mini.js文件链接到该命令。
    {
      "name": "vue-mini-plugin",
      "version": "1.0.0",
      "main": "index.js",
      "license": "MIT",
      "bin": {
        "vue-mini": "./bin/vue-mini.js"
      },
      "scripts": {
        "vue-mini": "vue-mini"
      },
      "dependence": {},
      "dependencies": {}
    }
    

(二)项目结构

[图片]

(三)编写vue-mini.js

bin目录下创建vue-mini.js文件,这个文件会作为 CLI 工具的入口文件。

#!/usr/bin/env node

import { spawn } from "child_process";
import { resolve, dirname } from "path";
import { fileURLToPath } from "url";

// 获取当前文件的路径
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

// 获取 mode 参数
const mode = process.argv.includes("--mode")
 ? process.argv[process.argv.indexOf("--mode") + 1]
  : "development";
console.log(`mode: ${mode}`);

// 运行不同的脚本
if (mode === "development") {
  const devScript = resolve(__dirname, "../scripts/development.js");

  const childProcess = spawn("node", [devScript], {
    stdio: "inherit",
    cwd: __dirname,
    shell: false,
  });

  childProcess.on("exit", (code, signal) => {
    if (code!== 0) {
      console.error(`服务启动失败,退出码: ${code}`);
    } else {
      console.log(`服务正常退出`);
    }
  });
} else {
  console.error("无效的模式参数");
}

(四)编写development.js

scripts目录下创建development.js文件,这个文件将负责实际的开发模式下的构建和启动过程。

import { spawn } from "child_process";
import { resolve, dirname } from "path";
import { fileURLToPath } from "url";

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

const serveScript = resolve(__dirname, "../serve.js");

const childProcess = spawn("node", [serveScript], {
  stdio: "inherit",
  cwd: __dirname,
  shell: false,
});

childProcess.on("exit", (code, signal) => {
  if (code!== 0) {
    console.error(`服务启动失败,退出码: ${code}`);
  } else {
    console.log(`服务正常退出`);
  }
});

(五)编写build.js

import express from "express";
import { dirname } from "path";
import { fileURLToPath } from "url";
import { mkdir, readFileSync, rm, writeFileSync } from "fs";
import { transform } from "esbuild";
import { parse } from "@vue/compiler-sfc";

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

const app = express();

const port = 3000;

if (process.argv.includes("--clean")) {
  rm(__dirname + "/dist", { recursive: true }, (err) => {
    if (err) console.log(err);
  });
}

mkdir(__dirname + "/dist/index", { recursive: true }, (err) => {
  if (err) console.log(err);
});

app.get("/", (req, res) => {
  res.sendFile(__dirname + "/src/index.html");
});

app.get("/*.js", (req, res) => {
  const path = req.path;
  const file = readFileSync(__dirname + "/src" + path, "utf-8");
  writeFileSync(__dirname + "/dist/index.js", file);
});

app.get("/*.css", (req, res) => {
  const path = req.path;
  const file = readFileSync(__dirname + "/src" + path, "utf-8");
  writeFileSync(__dirname + "/dist/index.css", file);
});

app.get("/*.ts", async (req, res) => {
  const path = req.path;
  const file = readFileSync(__dirname + "/src" + path, "utf-8");
  const transformResult = await transform(file, {
    loader: "ts",
    format: "esm",
    target: "es6",
  });
  writeFileSync(__dirname + "/dist/index.js", transformResult.code);
});

app.get("/*.vue", (req, res) => {
  const path = req.path;
  const fileContent = readFileSync(__dirname + "/src" + path, "utf-8");
  const parsed = parse(fileContent);

  if (parsed.descriptor.template) {
    writeFileSync(
      __dirname + "/dist/index/index.wxml",
      parsed.descriptor.template.content
    );
  }

  if (parsed.descriptor.scriptSetup) {
    writeFileSync(
      __dirname + "/dist/index/index.js",
      parsed.descriptor.scriptSetup.content
    );
  }

  if (parsed.descriptor.styles[0].content) {
    writeFileSync(
      __dirname + "/dist/index/index.wxss",
      parsed.descriptor.styles[0].content
    );
  }

  writeFileSync(__dirname + "/dist/index/index.json", "");

  const projectJson = readFileSync(
    __dirname + "/src/project.config.json",
    "utf-8"
  );
  writeFileSync(__dirname + "/dist/project.config.json", projectJson);
});

app.listen(port, () => {
  console.log(`http://localhost:${port}`);
});

(六)安装和测试

在项目根目录下运行以下命令,确保你的 CLI 工具可以运行:

  1. yarn
  2. yarn link

这将创建一个全局链接,允许你直接使用vue-mini命令。现在你可以测试运行以下命令:vue-mini --mode development

得到打包的文件:
在这里插入图片描述


http://www.kler.cn/a/304402.html

相关文章:

  • flask基础
  • vue中做一个最多输入一位小数且可以为负数的输入框(包含最前面最后面为小数点及多个-符号与前导零校验)
  • leetcode之hot100---2两数相加(C++)
  • 【NLP 17、NLP的基础——分词】
  • RGCL:A Review-aware Graph Contrastive Learning Framework for Recommendation
  • log4j2漏洞复现(CVE-2021-44228)
  • php 实现JWT
  • 用于客户支持的 GenAI:探索 Elastic Support Assistant
  • 如何让Windows控制台窗口不接受鼠标点击(禁用鼠标输入)
  • 前端工程师职业发展路线图
  • MADE A PIE 之动态树形图
  • 解决Docker镜像不可下载
  • 【GBase 8c V5_3.0.0 分布式数据库常用几个SQL】
  • 使用 Node Media Server 和 FFmpeg 创建直播流,推送本地视频
  • 在 Mac 上安装双系统会影响性能吗,安装双系统会清除数据吗?
  • 使用VSCode 安装SAP Fiori 开发所需插件
  • el-tree父子不互相关联时,手动实现全选、反选、子级全选、清空功能
  • Qt 构建报错 undefined reference to xxx
  • C++字符串中的string类操作
  • Humanize AI 简介
  • C和指针:函数
  • Leetcode 701-二叉搜索树中的插入操作
  • 安卓开发板_联发科MTK开发板使用ADB开发
  • Excel--不规则隔行填充底纹颜色
  • 【动手学深度学习】08 线性回归 + 基础优化算法(个人向笔记)
  • SpringCloud神领物流学习笔记:项目概述(一)