使用 vite 开发原生 html 网页

需要解决的问题

  • 打包目录结构不变
  • 可以复用 html 结构,打包结果为完整的 html
  • 打包 js、css 、图片等资源文件,文件名不能改变,代码不要拆分和拼接
  • 使用 tailwindcss
  • build 结果可直接给php后端使用

项目目录

  • src
    • components
    • style
      • js
      • css
      • images
      • lib 第三方库(jquery、swiper、video.js等)
    • ...html 文件
  • packages.json
  • build.js
  • vite.config.js

使用 vite-plugin-handlebars 插件实现开发复用 html

javascript 复制代码
import { defineConfig } from "vite";
import handlebars from "vite-plugin-handlebars";

export default defineConfig({
  root: "src",
  plugins: [
    handlebars({
      // 组件目录
      partialDirectory: "src/components",
    }),
  ],
  server: {
    port: 3000,
  },
});
html 复制代码
// componentes - header
<header>aaa</header>

// index.html - 自动导入
{{> header }}

自定义打包,解决使用 vite 打包会修改资源文件目录以及文件名

javascript 复制代码
// build.js - 简单的构建脚本
import fs from "fs";
import path from "path";
import { glob } from "glob";
import Handlebars from "handlebars";

const __dirname = path.dirname(new URL(import.meta.url).pathname);

// 注册 components
function registerComponents() {
  const partialsDir = path.resolve(__dirname, "src/components");
  if (!fs.existsSync(partialsDir)) return;

  const partialFiles = glob.sync("src/components/**/*.hbs");
  partialFiles.forEach((file) => {
    const name = path.basename(file, ".hbs");
    const content = fs.readFileSync(file, "utf8");
    Handlebars.registerPartial(name, content);
  });
}

// 编译 HTML 文件
function compileHtmlFiles() {
  const htmlFiles = glob.sync("src/*.html");
  const context = {};

  // 确保 dist 目录存在
  if (!fs.existsSync("dist")) {
    fs.mkdirSync("dist", { recursive: true });
  }

  htmlFiles.forEach((file) => {
    const content = fs.readFileSync(file, "utf8");
    const template = Handlebars.compile(content);
    const html = template(context);

    const outputFile = path.join("dist", path.basename(file));
    fs.writeFileSync(outputFile, html);
    console.log(`✓ 编译完成: ${file} -> ${outputFile}`);
  });
}

// 复制 styles 目录
function copyStyles() {
  const stylesDir = path.resolve(__dirname, "src/styles");
  const distStylesDir = path.resolve(__dirname, "dist/styles");

  if (!fs.existsSync(stylesDir)) {
    console.log("⚠️  src/styles 目录不存在");
    return;
  }

  // 递归复制目录
  function copyDir(src, dest) {
    if (!fs.existsSync(dest)) {
      fs.mkdirSync(dest, { recursive: true });
    }

    const entries = fs.readdirSync(src, { withFileTypes: true });
    entries.forEach((entry) => {
      const srcPath = path.join(src, entry.name);
      const destPath = path.join(dest, entry.name);

      if (entry.isDirectory()) {
        copyDir(srcPath, destPath);
      } else {
        fs.copyFileSync(srcPath, destPath);
      }
    });
  }

  copyDir(stylesDir, distStylesDir);
  console.log("✓ styles 目录复制完成");
}

// 清空 dist 目录
function cleanDist() {
  if (fs.existsSync("dist")) {
    fs.rmSync("dist", { recursive: true, force: true });
  }
  console.log("✓ 清空 dist 目录");
}

// 主构建函数
function build() {
  console.log("🚀 开始构建...");

  cleanDist();
  registerComponents();
  compileHtmlFiles();
  copyStyles();

  console.log("✅ 构建完成!");
}

build();

配置 packages.json 打包命令

json 复制代码
{
  "name": "phant-ai-vite",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "npx concurrently \"vite\" \"npx @tailwindcss/cli -i ./input.css -o ./src/styles/css/output.css --watch\"",
    "tw": "npx @tailwindcss/cli -i ./input.css -o ./src/styles/css/output.css --watch",
    "build": "npx @tailwindcss/cli -i ./input.css -o ./src/styles/css/output.css && node build.js"
  },
  "devDependencies": {
    "@types/jquery": "^3.5.32",
    "glob": "^11.0.2",
    "handlebars": "^4.7.8",
    "vite": "^6.3.5",
    "vite-plugin-handlebars": "^2.0.0"
  },
  "dependencies": {
    "@tailwindcss/cli": "^4.1.8",
    "tailwindcss": "^4.1.8"
  }
}
相关推荐
小小码农Come on12 小时前
QML访问子项内容
前端·javascript·html
幽络源小助理13 小时前
小六壬排盘工具源码 自适应双端 纯原生HTML+JS
前端·javascript·html
Championship.23.2414 小时前
Open Source Pipeline Skill深度解析:自动化开源贡献全流程
前端·javascript·html
凯瑟琳.奥古斯特16 小时前
Bootstrap快速上手指南
开发语言·前端·css·bootstrap·html
Dxy123931021617 小时前
HTML中的Canvas可以干哪些事情
前端·html
悟乙己17 小时前
解析 Agent 时代的 HTML PPT SKILLS: html-ppt-skill
前端·html·powerpoint
ZC跨境爬虫17 小时前
跟着 MDN 学 HTML day_2:(表单分组与高级输入控件实战)
前端·javascript·css·ui·html
Dxy123931021619 小时前
HTML中使用Canvas动态图形渲染:解锁Web交互新维度
前端·html·图形渲染
ZC跨境爬虫19 小时前
跟着 MDN 学 HTML day_1:(全套原生Input+表单结构拆解)
前端·css·ui·html
ZC跨境爬虫20 小时前
Apple官网复刻第二阶段day_6:(统一页脚模块封装+CSS公共复用体系落地)
前端·css·ui·重构·html