2024-12-05 21:14:41 +08:00
|
|
|
const fs = require("fs")
|
|
|
|
const path = require("path")
|
|
|
|
const uglify = require("uglify-js")
|
|
|
|
const CleanCSS = require("clean-css")
|
2024-12-06 18:05:40 +08:00
|
|
|
const brotli = require('brotli');
|
|
|
|
const base122 = require("./base122")
|
2024-12-05 21:14:41 +08:00
|
|
|
|
|
|
|
/** 一些配置参数
|
|
|
|
* - [注意] 路径问题.start脚本与web-mobile同层级,因此相对路径需要带上web-mobile;cocos在调用资源时没有web-mobile,需要在最后去掉
|
|
|
|
*/
|
|
|
|
const C = {
|
|
|
|
BASE_PATH: "web-mobile", // web-mobile包基础路径
|
|
|
|
RES_PATH: "web-mobile/assets", // web-mobile包下的res路径
|
|
|
|
RES_BASE64_EXTNAME_SET: new Set([ // 需要使用base64编码的资源后缀(根据项目自行扩充)
|
|
|
|
".png", ".jpg", ".webp", ".mp3",
|
|
|
|
]),
|
|
|
|
INPUT_LOADER_STARTER_JS: "single-html/loader-and-starter.js",
|
|
|
|
OUTPUT_RES_JS: "./web-mobile/asset-map.js", // 输出文件asset-map.js
|
|
|
|
OUTPUT_LOADER_STARTER_JS: "./web-mobile/loader-and-starter.js",
|
|
|
|
OUTPUT_INDEX_HTML: "dist/index.html", // 输出文件index.html的路径
|
|
|
|
INPUT_HTML_FILE: "./web-mobile/index.html",
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 读取文件内容
|
|
|
|
* - 特定后缀返回base64编码后字符串,否则直接返回文件内容字符串
|
|
|
|
* @param filepath
|
|
|
|
*/
|
|
|
|
function get_file_content(filepath) {
|
|
|
|
let file = fs.readFileSync(filepath)
|
|
|
|
return C.RES_BASE64_EXTNAME_SET.has(path.extname(filepath)) ? file.toString("base64") : file.toString()
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 获取路径下的所有子文件路径(深度遍历)
|
|
|
|
* @param filepath
|
|
|
|
*/
|
|
|
|
function get_all_child_file(filepath) {
|
|
|
|
let children = [filepath]
|
|
|
|
for (; ;) {
|
|
|
|
// 如果都是file类型的,则跳出循环
|
|
|
|
if (children.every(v => fs.statSync(v).isFile())) { break }
|
|
|
|
// 如果至少有1个directroy类型,则删除这一项,并加入其子项
|
|
|
|
children.forEach((child, i) => {
|
|
|
|
if (fs.statSync(child).isDirectory()) {
|
|
|
|
delete children[i]
|
|
|
|
let child_children = fs.readdirSync(child).map(v => `${child}/${v}`)
|
|
|
|
children.push(...child_children)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
return children
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 将所有res路径下的资源转化为res.js
|
|
|
|
* - 存储方式为:res-url(注意是相对的),res文件内容字符串或编码
|
|
|
|
*/
|
|
|
|
function write_resjs() {
|
|
|
|
// 读取并写入到一个对象中
|
|
|
|
let res_object = {}
|
|
|
|
get_all_child_file(C.RES_PATH).forEach(path => {
|
|
|
|
// 注意,存储时删除BASE_PATH前置
|
|
|
|
let store_path = path.replace(new RegExp(`^${C.BASE_PATH}/`), "")
|
|
|
|
res_object[store_path] = get_file_content(path)
|
|
|
|
})
|
|
|
|
// 写入文件
|
2024-12-06 18:05:40 +08:00
|
|
|
var compressedAssetsJs = Buffer.from(base122.encode(brotli.compress(new TextEncoder().encode(`window.assetMap=${JSON.stringify(res_object)}`))), 'utf-8')
|
|
|
|
fs.writeFileSync(C.OUTPUT_RES_JS, `eval(new TextDecoder().decode(window.unbrotli(base122ToArrayBuffer("${compressedAssetsJs}"))))`)
|
2024-12-05 21:14:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/** 将js文件转化为html文件内容(包括压缩过程) */
|
|
|
|
function get_html_code_by_js_file(js_filepath) {
|
|
|
|
let js = get_file_content(js_filepath)
|
|
|
|
let min_js = uglify.minify(js).code
|
|
|
|
return `<script type="text/javascript" charset="utf-8">${min_js}`
|
|
|
|
}
|
|
|
|
|
|
|
|
/** 将css文件转化为html文件内容(包括压缩过程) */
|
|
|
|
function get_html_code_by_css_file(css_filepath) {
|
|
|
|
let css = get_file_content(css_filepath)
|
|
|
|
let min_css = new CleanCSS().minify(css).styles
|
|
|
|
return `<style>${min_css}</style>`
|
|
|
|
}
|
|
|
|
|
|
|
|
function replaceRelativeCss(html) {
|
|
|
|
var reg = /\<link rel\="stylesheet" type\="text\/css" href\="(.+)"\/\>/g
|
|
|
|
var matchedCsss = html.match(reg);
|
|
|
|
|
|
|
|
matchedCsss.forEach((script) => {
|
|
|
|
var CssPath = reg.exec(script)[1];
|
|
|
|
html = html.replace(script, () => get_html_code_by_css_file(path.resolve(C.BASE_PATH, CssPath)))
|
|
|
|
});
|
|
|
|
|
|
|
|
return html;
|
|
|
|
}
|
|
|
|
|
|
|
|
function replaceRelativeScript(html) {
|
|
|
|
var matchedScripts = html.match(/\<script src\="(.+)"\>/g);
|
|
|
|
matchedScripts.forEach((script) => {
|
|
|
|
var reg = /(\<script src\=")(.+\.js)(".*>)/g;
|
|
|
|
var jsPath = reg.exec(script)[2];
|
2024-12-06 18:05:40 +08:00
|
|
|
console.log("写入", jsPath)
|
2024-12-05 21:14:41 +08:00
|
|
|
html = html.replace(script, () => get_html_code_by_js_file(path.resolve(C.BASE_PATH, jsPath)))
|
|
|
|
});
|
|
|
|
|
|
|
|
return html;
|
|
|
|
}
|
|
|
|
|
|
|
|
/** 执行任务 */
|
|
|
|
function do_task() {
|
|
|
|
// 前置:将res资源写成res.js
|
|
|
|
console.time("写入res")
|
|
|
|
write_resjs()
|
|
|
|
console.timeEnd("写入res")
|
|
|
|
|
|
|
|
fs.writeFileSync(C.OUTPUT_LOADER_STARTER_JS, get_file_content(C.INPUT_LOADER_STARTER_JS))
|
|
|
|
|
|
|
|
let html = get_file_content(C.INPUT_HTML_FILE)
|
|
|
|
|
|
|
|
console.time("替换js")
|
|
|
|
html = replaceRelativeScript(html)
|
|
|
|
html = replaceRelativeCss(html)
|
|
|
|
console.timeEnd("替换js")
|
|
|
|
|
|
|
|
// 写入文件并提示成功
|
|
|
|
console.time("输出html文件")
|
|
|
|
fs.writeFileSync(C.OUTPUT_INDEX_HTML, html)
|
|
|
|
console.timeEnd("输出html文件")
|
|
|
|
}
|
|
|
|
|
2025-01-08 13:52:22 +08:00
|
|
|
// 导出
|
|
|
|
module.exports = do_task
|