将几个 .js Uglify 到不同的文件夹(但具有相同的范围)

Uglify several .js to differents folders (but with same scope)

首先,对不起我的英语。

我正在开发一个系统的前端,其中有一些 js 文件将被连接并丑化为 app.js。没关系。但是,有些 js 文件会按需加载,即文件会在不同的文件夹中,按请求加载,并使用丑化后的 app.js 。 我的问题是我需要 uglify 全局变量和名称函数,当我 uglify 我的脚本时,文件不包含 "context" equal.

我的结构:

|project
  |scripts
    |core
      *.js
    |utils
      *.js
    |pages
      *.js
    app.js
    vendor.js
  |templates
    *.hbs // this files will be "compiled" to js with gulp-handlebars

我的构建结果:

|public
  |assets
    |js
      |pages // separated files, uglified with app.js scope
        *.js
      |templates // separated files, uglified with app.js scope
        *.js
      app.js // concat and uglify app.js, core and utils directories
      vendor.js // uglify separed keeping global variables (bower)

为了便于解释,假设public/assets/js/app.js有一个函数translate(a)。这只是接收变量 'a' 和 return 的值。 例如:

function translate(a) {
  return a;
}

首先,文件 app.js 是我 html 中唯一加载的文件。根据站点的区域设置,页面和模板目录的文件将动态加载到 html,使用 app.js 函数。

例如:public/assets/js/pages/*.jspublic/assets/js/templates/*.js

function consumeApp(a) {
  return translate(a);
}

我的问题是函数“translate”没有为页面和模板目录中的 js 文件定义,因为 uglify 不适用于需要相同 context/scope 的不同文件。

我的开发依赖(package.json):

"devDependencies": {
    "babel-core": "^6.4.0",
    "babel-preset-es2015": "^6.3.13",
    "babel-register": "^6.5.2",
    "bower": "^1.8.0",
    "del": "^1.1.1",
    "gulp": "^3.9.1",
    "gulp-autoprefixer": "^3.1.1",
    "gulp-babel": "^6.1.1",
    "gulp-bower": "0.0.13",
    "gulp-browserify": "^0.5.1",
    "gulp-cache": "^0.4.6",
    "gulp-concat": "^2.6.1",
    "gulp-cssnano": "^2.1.2",
    "gulp-declare": "^0.3.0",
    "gulp-eslint": "^3.0.1",
    "gulp-handlebars": "^4.0.0",
    "gulp-htmlmin": "^3.0.0",
    "gulp-imagemin": "^3.2.0",
    "gulp-include": "^2.3.1",
    "gulp-load-plugins": "^1.5.0",
    "gulp-plumber": "^1.1.0",
    "gulp-precompile-handlebars": "^2.0.5",
    "gulp-sass": "^3.1.0",
    "gulp-size": "^2.1.0",
    "gulp-sourcemaps": "^2.6.0",
    "gulp-sync": "^0.1.4",
    "gulp-uglify": "^2.1.2",
    "gulp-wrap": "^0.13.0",
    "handlebars": "^4.0.10",
    "jscs": "^3.0.7",
    "uniq": "^1.0.1",
    "webpack": "^2.6.1",
    "webpack-stream": "^3.2.0"
  }

我的 gulpfile(只有 uglify 部分):

const gulp = require('gulp');
const gulpsync = require('gulp-sync')(gulp);
const gulpLoadPlugins = require('gulp-load-plugins');
const del = require('del');
const concat = require('gulp-concat');
const webpack = require('webpack-stream');

const $ = gulpLoadPlugins();

// .... uglify tasks run after all be in public

gulp.task('scripts:uglify', gulpsync.sync([
    'scripts:uglify-vendor',
    'scripts:uglify-app'
]));

gulp.task('scripts:uglify-app', () => {
    return gulp.src([
        'public/assets/js/**/*js',
        '!public/assets/js/vendor.js',
    ]).pipe($.uglify({
        mangle: {
            toplevel: true
        }
    }))
        .pipe(gulp.dest('public/assets/js'));
});

gulp.task('scripts:uglify-vendor', () => {
    return gulp.src('public/assets/js/vendor.js')
        .pipe($.uglify({mangle: false}))
        .pipe(gulp.dest('public/assets/js'));
});

有人知道为什么吗? 谢谢。

我在 gulpfile 中创建了一个方法,使用 node.js,"randomizes" 全局变量和特定函数来解决我的问题。为此,我将所有全局变量分隔在一个名为 ./scripts/core/_variables.js 的唯一文件中,其中每个变量都声明为第 行。我动态地映射了所有全局变量,与函数名称连接,并替换了 ./public/assets/js/**/*.js 中已经构建的文件。 下面的算法可以配置函数名和目录,可以是随机的。

const fs = require('fs'); // added
const prettyjson = require('prettyjson'); // added

const consoleLog = (msg) => {
    console.log(prettyjson.render(msg));
};

gulp.task('run-build', gulpsync.sync([
    'myTasks', // tasks to run build
]]), () => {
    return gulp.src('public/assets/**/*').pipe($.size({title: 'build', gzip: true}));
});

gulp.task('build', gulpsync.sync(['run-build', 'randomly']), () => {
    return true;
});

gulp.task('randomly', () => {
    return new Promise( function(resolve) {

        // set here the functions name to randomly
        function getFunctions() {
            consoleLog('get functions name');
            return [
                'translate',
                'myFirstFunction',
                'mySecondFunction'
            ]
        }

        // get automatically variables in ./scripts/core/_variables.js
        function getVariables() {
            consoleLog('start global variables loader');

            var fileContent = fs.readFileSync('./scripts/core/_variables.js', 'utf8');
            var a = fileContent.split('=');
            var consts = [],
                lets = [];
            for (var i = 0; i < a.length; i++) {
                var c = a[i].split('const '),
                    l = a[i].split('let ');
                if (c[1])
                    consts.push(c[1].toString().trim());
                if (l[1])
                    lets.push(l[1].toString().trim());
            }
            consoleLog('finished global variables loader');
            return consts.concat(lets);
        }

        // set random unique names to variables and functions
        function setRandomNames(variables) {
            return new Promise( function(resolve) {
                consoleLog('start fake names generator');
                var fakeNames = [];
                var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';

                function existFakeName(name) {
                    for(var i in fakeNames)
                        if(fakeNames[i].fake === name)
                            return true;
                    return false;
                }

                function newNames() {
                    return new Promise( function(resolve) {
                        var name = '';
                        for (var i = 0; i < 10; i++)
                            name += possible.charAt(Math.floor(Math.random() * possible.length));
                        if (fakeNames.length <= variables.length && !existFakeName(name)) {
                            var item = fakeNames.length;
                            fakeNames.push({
                                name: variables[item],
                                fake: name
                            });
                            if (fakeNames.length === variables.length) {
                                consoleLog(fakeNames);
                                consoleLog('finished fake names generator');
                                resolve();
                            }
                            else
                                resolve(newNames());
                        }
                        else
                            resolve(newNames());
                    });
                }
                newNames().then(() => {
                    resolve(fakeNames);
                })
            });
        }

        function listDirectory(dir) {
            return new Promise((resolve) => {
                var listFiles = fs.readdirSync(dir);
                var response = [];
                for (var i in listFiles) {
                    response.push(dir + listFiles[i]);
                }
                resolve(response);
            });
        }
        function replaceFile(file, fakes) {
            return new Promise( function(resolve) {
                // consoleLog('start replace file ' + file);

                var fileContent = fs.readFileSync(file, 'utf8');
                for (var i in fakes)
                    fileContent = fileContent.split(fakes[i].name).join(fakes[i].fake);
                resolve(writeFile(file, fileContent));
            })
        }
        function writeFile(file, fileContent) {
            return new Promise( function(resolve) {
                fs.writeFile(file, fileContent, function (err) {
                    if (err) {
                        consoleLog('error ' + file);
                        resolve();
                    }

                    // consoleLog('finished replace file and saved: ' + file);
                    resolve();
                });
            });
        }

        consoleLog('start randomly');
        setRandomNames(getVariables().concat(getFunctions())).then( function(fakes) {
            consoleLog('start list directories');
            Promise.all([
                listDirectory('./public/assets/js/pages/')
            ]).then( function(response) {

                consoleLog('finished list directories');

                var files = ['./public/assets/js/app.js']; // change app.js
                for (var i in response)
                    files = files.concat(response[i]);

                var promises = [];
                for(var file in files)
                    promises.push(replaceFile(files[file], fakes));

                Promise.all(promises).then( function() {
                    consoleLog('all files replaced and saved');
                    consoleLog('finished randomly');
                    resolve();
                    return true;
                });
            });
        });
    });
});