使用 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"
  }
}
相关推荐
三乐2284 小时前
简单定位布局
html
Zzzzmo_4 小时前
【HTML+CSS+JavaScript】01 HTML标签
html
软件技术NINI9 小时前
泉州html+css 4页
前端·javascript·css·html
Python大数据分析@12 小时前
HTML会代替Markdown吗?为什么?
前端·html
一棵树735112 小时前
js总结介绍
前端·javascript·html
ZC跨境爬虫12 小时前
跟着 MDN 学CSS day_2:(连接样式表与选择器的实战艺术)
java·前端·css·ui·html·媒体
ZC跨境爬虫12 小时前
跟着 MDN 学CSS day_1:(CSS 基石与色彩的艺术)
前端·javascript·css·ui·html
ZC跨境爬虫13 小时前
模块化烹饪小程序开发日记 Day4:网络层基础设施与接口治理实践
前端·javascript·数据库·ui·html
霜落花轻扬1 天前
在新选项卡中显示链接【html中 target=“_blank“】
前端·html
Revio Lab1 天前
把 AI 生成的 HTML 当 Markdown 来管:Web-Doc 自托管文档站实践
前端·html·mcp·html文档