• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

H5原生项目的压缩、混淆html-minifier 、javascript-obfuscator

武飞扬头像
忍冬 ⁡⁡
帮助1

为了防止项目被别人轻松抄袭,所以对代码的压缩、混淆还是很有必要的


一、常见插件介绍

  1. js压缩:terser、uglifyjs
  2. js混淆:javascript-obfuscator
  3. css压缩:postcss、clean-css
  4. html、css、js压缩:html-minifier

这里我们使用 html-minifier(压缩html、css)javascript-obfuscator(js混淆)

二、开始吧

  1. 运行环境:node(v14.17.6)
  2. 安装依赖:npm i html-minifier javascript-obfuscator
  3. 运行:
    1. 根据自己的项目修改根目录修改不进行处理的文件(夹)、修改原样输出的文件(如图片、字体文件、min文件)
    2. node main.js
  4. main.js 代码如下:
  1.  
    const fs = require('fs');
  2.  
    const path = require('path');
  3.  
    const minify = require('html-minifier').minify;
  4.  
    const JO = require("javascript-obfuscator");
  5.  
     
  6.  
    // 项目根目录
  7.  
    let sRootPath = 'ui'
  8.  
     
  9.  
    fnTravel(sRootPath, fnCompressHtmlCss)
  10.  
    console.log("文件处理结束")
  11.  
     
  12.  
    /**
  13.  
    * 遍历文件
  14.  
    * @params {*} dir 文件夹
  15.  
    * @params {*} callback 回调函数
  16.  
    */
  17.  
    function fnTravel(dir, callback) {
  18.  
    // 同步读取指定目录的内容
  19.  
    let aFiles = fs.readdirSync(dir, 'utf8'), aFilterPath = ['.git', '.idea', 'html', 'README'];
  20.  
    aFiles.forEach((file) => {
  21.  
    // 获得完整路径
  22.  
    let pathname = path.join(dir, file)
  23.  
    // 判断是否处理
  24.  
    let bIsHandle = aFilterPath.some(item => pathname.includes(item));
  25.  
    if(!bIsHandle) {
  26.  
    // 同步获取详细信息
  27.  
    let stats = fs.statSync(pathname);
  28.  
    if (stats.isDirectory()) {
  29.  
    // 文件夹
  30.  
    fnTravel(pathname, callback)
  31.  
    } else {
  32.  
    // 文件
  33.  
    try {
  34.  
    if (pathname.endsWith('js')) {
  35.  
    // js 文件
  36.  
    fnObfuscatorJs(pathname)
  37.  
    } else {
  38.  
    // 其他文件
  39.  
    callback(pathname)
  40.  
    }
  41.  
    } catch (e) {
  42.  
    console.error("压缩失败:" pathname);
  43.  
    console.error(e);
  44.  
    }
  45.  
    }
  46.  
    }
  47.  
    })
  48.  
    }
  49.  
     
  50.  
    /**
  51.  
    * 压缩 html、css 文件方法
  52.  
    * @params {*} path 文件路径
  53.  
    */
  54.  
    function fnCompressHtmlCss(path) {
  55.  
    let sTargetPath = path.replace('ui', 'dist'),
  56.  
    sCompressData = null, data = null;
  57.  
    if (!path.includes('img') && !path.includes('fonts')) {
  58.  
    // 获取文件内容
  59.  
    data = fs.readFileSync(path, 'utf8')
  60.  
    if(!path.endsWith('.min.css')) {
  61.  
    // 压缩后的文件内容
  62.  
    sCompressData = minify(data, {
  63.  
    collapseWhitespace: true, // 删除html里的空格 达到html的压缩
  64.  
    removeAttributeQuotes: true, // 尽可能删除html标签里的双引号 达到html的压缩
  65.  
    removeComments: true, //删除html中的注释
  66.  
    removeCommentsFromCDATA: true, //从脚本和样式删除的注释
  67.  
    minifyCSS: true, // 压缩css
  68.  
    })
  69.  
    }
  70.  
    }
  71.  
    let result = sCompressData ? sCompressData : data;
  72.  
    // 将数据同步写入文件
  73.  
    fnWriteFileRecursive(path, sTargetPath, result, (err) => {
  74.  
    if (err) console.error(err);
  75.  
    console.log('compress--[' path ']--success');
  76.  
    })
  77.  
    }
  78.  
     
  79.  
    /**
  80.  
    * 压缩、混淆js方法
  81.  
    * @params {*} path 文件路径
  82.  
    */
  83.  
    function fnObfuscatorJs(path) {
  84.  
    let sTargetPath = path.replace('ui', 'dist'),
  85.  
    sObfuscateCode = null;
  86.  
    // 获取文件内容
  87.  
    let data = fs.readFileSync(path, 'utf8')
  88.  
    if (!sTargetPath.endsWith('.min.js')) {
  89.  
    // 进行混淆
  90.  
    sObfuscateCode = JO.obfuscate(data, {
  91.  
    compact: true, // 压缩
  92.  
    controlFlowFlattening: true,
  93.  
    controlFlowFlatteningThreshold: 1,
  94.  
    numbersToExpressions: true,
  95.  
    simplify: true,
  96.  
    shuffleStringArray: true,
  97.  
    splitStrings: true,
  98.  
    stringArrayThreshold: 1,
  99.  
    });
  100.  
    }
  101.  
    // getObfuscatedCode() 返回混淆后的代码字符串,调用 toString 方法也会返回混淆代码
  102.  
    let sResultCode = sObfuscateCode ? sObfuscateCode.getObfuscatedCode() : data;
  103.  
    fnWriteFileRecursive(path, sTargetPath, sResultCode, (err) => {
  104.  
    if (err) console.error(err);
  105.  
    console.log('compress--[' path ']--success');
  106.  
    })
  107.  
    }
  108.  
     
  109.  
    /**
  110.  
    * 创建目录并写入文件
  111.  
    * @params {*} sFromPath 来源路径
  112.  
    * @params {*} sTargetPath 目标路径
  113.  
    * @params {*} buffer 文件内容
  114.  
    * @params {*} callback 回调函数
  115.  
    * */
  116.  
    function fnWriteFileRecursive(sFromPath, sTargetPath, buffer, callback) {
  117.  
    let lastPath = sTargetPath.substring(0, sTargetPath.lastIndexOf("\\"));
  118.  
    // 创建目录
  119.  
    fs.mkdir(lastPath, {
  120.  
    recursive: true
  121.  
    }, (err) => {
  122.  
    if (err) return callback(err);
  123.  
    if (sTargetPath.includes('img') || sTargetPath.includes('fonts')) {
  124.  
    // 处理图片、字体文件
  125.  
    let readStream = fs.createReadStream(sFromPath); // 逐块读取文件
  126.  
    let writeStream = fs.createWriteStream(sTargetPath); // 对指定文件创建一个“可写数据流”
  127.  
    readStream.pipe(writeStream); // 将文件数据流导向 writeStream 对象
  128.  
    } else {
  129.  
    // 处理html、css、js文件
  130.  
    fs.writeFileSync(sTargetPath, buffer, function (err) {
  131.  
    if (err) return callback(err);
  132.  
    });
  133.  
    }
  134.  
    });
  135.  
    }

知识点扩展

  1. 在写入文件之前,首先使用 mkdir(第一个参数是目录路径,第二个是权限,第三个是回调函数)方法新建目录,防止因为路径不存在而报错
  2. node.js 内置的 fs模块是文件系统模块,负责读写文件,fs模块还提供了异步和同步的方法
    1. 使用异步方法执行IO(输入/输出)操作时,JS代码不需要等待,在传入回调函数后,会继续执行后续代码
    2. 使用同步方法执行IO时,则需要等待函数返回
  3. node.js 中readFile和createReadStream函数的区别:
    1. readFile函数异步读取文件内容,并存储在内存中,然后才能使用;优点是符合直觉,流程自然。缺点是如果遇到大文件,要花费很长时间,才能进入数据处理的步骤
    2. createReadStream使用一个可读的流,逐块读取文件,而不是全部存储在内存中,同时每当系统读入一小块数据时,就会触发一个事件,只要监听这个事件(data)就能掌握执行进度,做出相应的数据处理,这样一来 createReadStream 使用更少的内存和更快的速度来优化文件的读取操作。

参考文章

  1.  
    https://segmentfault.com/a/1190000040502426
  2.  
    https://blog.csdn.net/qq_37667074/article/details/108356269
  3.  
    https://blog.csdn.net/foupwang/article/details/103306332
  4.  
    https://blog.csdn.net/Liheishuai/article/details/124625069

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgekheg
系列文章
更多 icon
同类精品
更多 icon
继续加载