You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

已用ncp实现目录复制,如何通过Node.js与npm脚本压缩HTML/CSS/JS?

嘿,我来帮你搞定这个需求!你已经用ncp搞定了目录复制,接下来咱们把压缩功能加进去——完全不用Gulp,纯Node.js+npm脚本就能实现,包你满意~

整体思路

咱们的流程是:先把src目录完整复制到public,再遍历public里的HTML、CSS、JS文件,用专门的压缩工具逐个处理。这样既保留了你已有的复制逻辑,又能无缝集成压缩功能。

步骤1:安装必要的依赖

除了你已经用的ncp,还需要几个轻量的压缩工具和文件查找工具,直接用npm安装就行:

npm install ncp html-minifier-terser clean-css terser glob --save-dev

这里给你选的都是目前维护活跃、压缩效果不错的工具:

  • html-minifier-terser:压缩HTML,还能顺带处理HTML里的内联JS/CSS
  • clean-css:专注压缩CSS,支持各种高级配置
  • terser:是uglify-js的现代替代,压缩JS的同时还能处理ES6+语法
  • glob:用来快速查找目标目录里的所有指定类型文件,比手动遍历目录省心多了
步骤2:编写整合复制+压缩的Node.js脚本

新建一个build.js文件,把复制和压缩逻辑整合进去,代码里加了详细注释,你可以按需调整:

const ncp = require('ncp').ncp;
const glob = require('glob');
const htmlMinifier = require('html-minifier-terser');
const CleanCSS = require('clean-css');
const terser = require('terser');
const fs = require('fs');
const path = require('path');

// 复制目录的配置(和你原来的保持一致)
ncp.limit = 16;
const copyOptions = { 
  clobber: true, // 允许覆盖已存在的文件/目录
  stopOnErr: true // 出错时立即停止
};

// 压缩单个HTML文件的函数
async function minifyHtml(filePath) {
  try {
    const content = fs.readFileSync(filePath, 'utf8');
    const minifiedContent = htmlMinifier.minify(content, {
      collapseWhitespace: true, // 折叠空白字符
      removeComments: true, // 移除注释
      minifyJS: true, // 顺便压缩HTML内的JS代码
      minifyCSS: true // 顺便压缩HTML内的CSS代码
    });
    fs.writeFileSync(filePath, minifiedContent, 'utf8');
    console.log(`✅ 已压缩HTML: ${filePath}`);
  } catch (err) {
    console.error(`❌ 压缩HTML出错 ${filePath}:`, err);
  }
}

// 压缩单个CSS文件的函数
async function minifyCss(filePath) {
  try {
    const content = fs.readFileSync(filePath, 'utf8');
    const minifiedContent = new CleanCSS().minify(content).styles;
    fs.writeFileSync(filePath, minifiedContent, 'utf8');
    console.log(`✅ 已压缩CSS: ${filePath}`);
  } catch (err) {
    console.error(`❌ 压缩CSS出错 ${filePath}:`, err);
  }
}

// 压缩单个JS文件的函数
async function minifyJs(filePath) {
  try {
    const content = fs.readFileSync(filePath, 'utf8');
    const minifyResult = terser.minify(content);
    if (minifyResult.error) throw minifyResult.error;
    
    fs.writeFileSync(filePath, minifyResult.code, 'utf8');
    console.log(`✅ 已压缩JS: ${filePath}`);
  } catch (err) {
    console.error(`❌ 压缩JS出错 ${filePath}:`, err);
  }
}

// 批量处理所有需要压缩的文件
async function processMinification() {
  // 查找public目录下所有HTML文件
  const htmlFiles = await glob.glob('public/**/*.html');
  for (const file of htmlFiles) await minifyHtml(file);

  // 查找public目录下所有CSS文件
  const cssFiles = await glob.glob('public/**/*.css');
  for (const file of cssFiles) await minifyCss(file);

  // 查找public目录下所有JS文件
  const jsFiles = await glob.glob('public/**/*.js');
  for (const file of jsFiles) await minifyJs(file);
}

// 主流程:先复制目录,再执行压缩
ncp('src', 'public', copyOptions, async function(err) {
  if (err) {
    return console.error('❌ 目录复制失败:', err);
  }
  console.log('🎉 目录复制完成!开始压缩文件...');
  await processMinification();
  console.log('🎉 所有文件压缩完成!');
});
步骤3:配置npm脚本

打开你的package.json,在scripts字段里添加一条build命令:

"scripts": {
  "build": "node build.js"
}

之后只要在终端运行npm run build,就能自动完成目录复制+文件压缩的整套流程啦!

可选优化提示
  • 如果你不想覆盖public里的原文件,可以修改压缩逻辑,把压缩后的文件输出到新目录(比如dist),但根据你的需求,直接覆盖复制后的文件是最直接的方案。
  • 每个压缩工具都有丰富的配置项,比如你想给JS开启变量混淆、给CSS保留特定注释,都可以去对应工具的文档里找配置参数调整。

内容的提问来源于stack exchange,提问作者StephD

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:18:11