使用 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"
  }
}
相关推荐
AA-代码批发V哥2 小时前
HTML之语义化标签与多媒体标签
html
像风一样自由20203 小时前
HTML与JavaScript:构建动态交互式Web页面的基石
前端·javascript·html
Hilaku9 小时前
深入CSS层叠的本质:@layer如何优雅地解决样式覆盖与!important滥用问题
前端·css·html
ac.char10 小时前
Golang读取ZIP压缩包并显示Gin静态html网站
golang·html·gin
每天开心10 小时前
深入理解 CSS 选择器:从基础到高级
css·html·ai编程
撰卢11 小时前
如何提高网站加载速度速度
前端·javascript·css·html
sophister11 小时前
Flex 布局中容易踩的那些坑,你踩过几个?
前端·css·html
呆呆的心15 小时前
揭秘 CSS 伪元素:不用加标签也能玩转出花的界面技巧 ✨
前端·css·html
WildBlue15 小时前
🧊 HTML5 王者对象 Blob - 二进制世界的魔法沙漏
前端·javascript·html
wuxuanok15 小时前
Web前端开发-HTML、CSS
前端·css·html