使用 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"
  }
}
相关推荐
ssshooter36 分钟前
复习 CSS Flex 和 Grid 布局
前端·css·html
UNbuff_02 小时前
HTML 中的 CSS 使用说明
css·html·tensorflow
wallflower20204 小时前
Web Workers:前端多线程解决方案
性能优化·html
charlie1145141915 小时前
前端三件套简单学习:HTML篇1
开发语言·前端·学习·html
正义的大古19 小时前
OpenLayers常用控件 -- 章节六:全屏控件教程
前端·javascript·html·openlayers
OC溥哥99920 小时前
Flask论坛与个人中心页面开发教程完整详细版
后端·python·flask·html
wangbing11251 天前
界面规范8-文字
前端·javascript·html
jingling5551 天前
uniapp | 解决组件样式不生效问题
前端·css·uni-app·html·学习方法
小菜全1 天前
使用UniApp实现下拉框和表格组件页面
开发语言·前端·javascript·elementui·前端框架·html
luckyzlb1 天前
02- html && css
前端·css·html