eym9gquw1

23朵毒蘑菇

优化了下我的后端代码打包方法

后端需要操作文件夹,所以用打包到一个文件里的打包方式是不行的,打包后文件结构不需要变化就行了

打包|NODE

2023-05-17 16:01:46 已有版本 1 个 show:0.86kTYPE: blog

node 后端代码还是得打个包在部署到服务器上,写了个简易的打包方法,压缩js,css,html

因为后端需要操作文件夹,所以用打包到一个文件里的打包方式是不行的,打包后文件结构不需要变化就行了,可能有更好的解决方案,但写一个可以充充电嘛

方便的很哇

/**
 * 项目打包操作
 * 复制除了js的文件
 * js文件进行压缩
 */

const path = require('path');
const fs = require('fs');
const glob = require('glob');
const makeDir = require('make-dir');
const UglifyJS = require("uglify-js");
const copyFile = require('fs-copy-file');
const CleanCSS = require('clean-css');
const htmlMinifier = require('html-minifier');
const Postcss = require("postcss");
const postcssPresetEnv = require("postcss-preset-env");
const htmlparser2 = require("htmlparser2");
// 设置插件
const processor = Postcss([postcssPresetEnv({
    stage: 2,
    browsers: ['> 0%','Android 2.3','iOS 3.2','Safari 3.1','IE 10'],  //支持大多数浏览器
})]);

/** 分割 */
function splitFileType(path){
    path = path || '';
    const list = path.split('.');
    return list;
}

/** 表示是js文件 */
function isJsFile(path){
    const list = splitFileType(path);
    if(list.length <= 1) return false;
    if(list[list.length-1] === 'js') return true;
    return false;
}
/** 表示是css文件 */
function isCssFile(path){
    const list = splitFileType(path);
    if(list.length <= 1) return false;
    if(list[list.length-1] === 'css') return true;
    return false;
}
/** 表示是html文件 */
function isHtmlFile(path){
    const list = splitFileType(path);
    if(list.length <= 1) return false;
    if(list[list.length-1] === 'art') return true;
    if(list[list.length-1] === 'html') return true;
    return false;
}
/** 格式化css */
async function formatCss(css,isHtml){
    if(isHtml){
        // html的话要先解析出css
        let isCssTag;
        let cssStringList = [];  //css字符串
        const parser = new htmlparser2.Parser({
            onopentag(name) {
                if (name === "style") {
                    isCssTag = true;
                }else{
                    isCssTag = false;
                }
            },
            onclosetag(name){
                if (name === "style") {
                    isCssTag = false;
                }
            },
            ontext(text) {
                if(!isCssTag || !text) return;
                cssStringList.push(text);
            },
        });
        parser.write(css);
        await Promise.all(cssStringList.map(item=>{
            return processor.process(item, {from:undefined}).then(result => {
                if(!result.css) return;
                css = css.replace(item,result.css);
            });
        }));
        parser.end();
        return css;
    }else{
        return processor.process(css, {from:undefined}).then(result => {
            return result.css || css;
        });
    }
}

console.log('biuld start:----------');
console.time();
process.on('exit',() => {
    console.log("biuld end:----------");
    console.timeEnd();
});
// 遍历文件
glob('**/*', {
    ignore:['node_modules/**','dist/**','biuld.js','.git/**'],
    dot:true,
}, async function (er, files) {
    if(er){
        console.error(er);
        return;
    }
    await makeDir(path.join(__dirname,'.','dist'));
    files.forEach(async (item)=>{
        const path_ = path.join(__dirname,'.',item);
        const path__ = path.join(__dirname,'.','dist',item);
        const isFile = fs.statSync(path_).isFile();  //表示是文件
        if(!isFile){  //表示是目录,建立
            await makeDir(path__);
        }else{
            const isJs = isJsFile(item);
            const isCss = isCssFile(item);
            const isHtml = isHtmlFile(item);
            if(isJs){
                // js文件 代码进行压缩
                const content = fs.readFileSync(path_, "utf8");
                try {
                    const output = UglifyJS.minify(content, {
                        mangle: {
                            toplevel: true,
                        },
                        nameCache: {},
                    });
                    fs.writeFileSync(path__, output.code, "utf8");
                    console.log('压缩完成:',item);
                } catch {
                    console.log('压缩失败--:',item);
                }
            }else if(isCss){  //压缩css文件
                let content = fs.readFileSync(path_, "utf8");
                try {
                    content = await formatCss(content);
                    const output = new CleanCSS({}).minify(content);
                    fs.writeFileSync(path__, output.styles, "utf8");
                    console.log('压缩完成:',item);
                } catch {
                    console.log('压缩失败--:',item);
                }
            }else if(isHtml){  //压缩html文件
                let content = fs.readFileSync(path_, "utf8");
                try {
                    content = await formatCss(content,true);  //格式化css
                    const output = htmlMinifier.minify(content, {
                        collapseWhitespace: true, // 删除html里的空格 达到html的压缩
                        removeComments: true, //删除html中的注释
                        removeCommentsFromCDATA: true, //从脚本和样式删除的注释
                        minifyURLs:true,
                        minifyJS: (test)=>{  //压缩html中的js
                            test = UglifyJS.minify(test,{
                                mangle: {
                                    toplevel: true,
                                },
                                nameCache: {},
                            }).code;
                            return test;
                        },
                        minifyCSS: false,  //模板引擎的内联样式可能丢失
                    });
                    fs.writeFileSync(path__, output, "utf8");
                    console.log('压缩完成:',item);
                } catch {
                    console.log('压缩失败--:',item);
                }
            }else{
                copyFile(path_, path__,(err) => {
                    if (err) {
                        console.error('创建失败--:',item);
                        return;
                    }
                });
            }
        }
    });
});

打包还是挺方便的。