optimize.js 8.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
'use strict';
Object.defineProperty(exports, "__esModule", { value: true });
exports.minifyTask = exports.optimizeTask = exports.loaderConfig = void 0;
const es = require("event-stream");
const gulp = require("gulp");
const concat = require("gulp-concat");
const filter = require("gulp-filter");
const fancyLog = require("fancy-log");
const ansiColors = require("ansi-colors");
const path = require("path");
const pump = require("pump");
const VinylFile = require("vinyl");
const bundle = require("./bundle");
const i18n_1 = require("./i18n");
const stats_1 = require("./stats");
const util = require("./util");
const REPO_ROOT_PATH = path.join(__dirname, '../..');
function log(prefix, message) {
    fancyLog(ansiColors.cyan('[' + prefix + ']'), message);
}
function loaderConfig() {
    const result = {
        paths: {
            'vs': 'out-build/vs',
            'vscode': 'empty:'
        },
        amdModulesPattern: /^vs\//
    };
    result['vs/css'] = { inlineResources: true };
    return result;
}
exports.loaderConfig = loaderConfig;
const IS_OUR_COPYRIGHT_REGEXP = /Copyright \(C\) Microsoft Corporation/i;
function loader(src, bundledFileHeader, bundleLoader) {
    let sources = [
        `${src}/vs/loader.js`
    ];
    if (bundleLoader) {
        sources = sources.concat([
            `${src}/vs/css.js`,
            `${src}/vs/nls.js`
        ]);
    }
    let isFirst = true;
    return (gulp
        .src(sources, { base: `${src}` })
        .pipe(es.through(function (data) {
        if (isFirst) {
            isFirst = false;
            this.emit('data', new VinylFile({
                path: 'fake',
                base: '.',
                contents: Buffer.from(bundledFileHeader)
            }));
            this.emit('data', data);
        }
        else {
            this.emit('data', data);
        }
    }))
        .pipe(concat('vs/loader.js')));
}
function toConcatStream(src, bundledFileHeader, sources, dest, fileContentMapper) {
    const useSourcemaps = /\.js$/.test(dest) && !/\.nls\.js$/.test(dest);
    // If a bundle ends up including in any of the sources our copyright, then
    // insert a fake source at the beginning of each bundle with our copyright
    let containsOurCopyright = false;
    for (let i = 0, len = sources.length; i < len; i++) {
        const fileContents = sources[i].contents;
        if (IS_OUR_COPYRIGHT_REGEXP.test(fileContents)) {
            containsOurCopyright = true;
            break;
        }
    }
    if (containsOurCopyright) {
        sources.unshift({
            path: null,
            contents: bundledFileHeader
        });
    }
    const treatedSources = sources.map(function (source) {
        const root = source.path ? REPO_ROOT_PATH.replace(/\\/g, '/') : '';
        const base = source.path ? root + `/${src}` : '.';
        const path = source.path ? root + '/' + source.path.replace(/\\/g, '/') : 'fake';
        const contents = source.path ? fileContentMapper(source.contents, path) : source.contents;
        return new VinylFile({
            path: path,
            base: base,
            contents: Buffer.from(contents)
        });
    });
    return es.readArray(treatedSources)
        .pipe(useSourcemaps ? util.loadSourcemaps() : es.through())
        .pipe(concat(dest))
        .pipe(stats_1.createStatsStream(dest));
}
function toBundleStream(src, bundledFileHeader, bundles, fileContentMapper) {
    return es.merge(bundles.map(function (bundle) {
        return toConcatStream(src, bundledFileHeader, bundle.sources, bundle.dest, fileContentMapper);
    }));
}
const DEFAULT_FILE_HEADER = [
    '/*!--------------------------------------------------------',
    ' * Copyright (C) Microsoft Corporation. All rights reserved.',
    ' *--------------------------------------------------------*/'
].join('\n');
function optimizeTask(opts) {
    const src = opts.src;
    const entryPoints = opts.entryPoints;
    const resources = opts.resources;
    const loaderConfig = opts.loaderConfig;
    const bundledFileHeader = opts.header || DEFAULT_FILE_HEADER;
    const bundleLoader = (typeof opts.bundleLoader === 'undefined' ? true : opts.bundleLoader);
    const out = opts.out;
    const fileContentMapper = opts.fileContentMapper || ((contents, _path) => contents);
    return function () {
121
        const sourcemaps = require('gulp-sourcemaps');
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
        const bundlesStream = es.through(); // this stream will contain the bundled files
        const resourcesStream = es.through(); // this stream will contain the resources
        const bundleInfoStream = es.through(); // this stream will contain bundleInfo.json
        bundle.bundle(entryPoints, loaderConfig, function (err, result) {
            if (err || !result) {
                return bundlesStream.emit('error', JSON.stringify(err));
            }
            toBundleStream(src, bundledFileHeader, result.files, fileContentMapper).pipe(bundlesStream);
            // Remove css inlined resources
            const filteredResources = resources.slice();
            result.cssInlinedResources.forEach(function (resource) {
                if (process.env['VSCODE_BUILD_VERBOSE']) {
                    log('optimizer', 'excluding inlined: ' + resource);
                }
                filteredResources.push('!' + resource);
            });
            gulp.src(filteredResources, { base: `${src}`, allowEmpty: true }).pipe(resourcesStream);
            const bundleInfoArray = [];
            if (opts.bundleInfo) {
                bundleInfoArray.push(new VinylFile({
                    path: 'bundleInfo.json',
                    base: '.',
                    contents: Buffer.from(JSON.stringify(result.bundleData, null, '\t'))
                }));
            }
            es.readArray(bundleInfoArray).pipe(bundleInfoStream);
        });
        const result = es.merge(loader(src, bundledFileHeader, bundleLoader), bundlesStream, resourcesStream, bundleInfoStream);
        return result
            .pipe(sourcemaps.write('./', {
            sourceRoot: undefined,
            addComment: true,
            includeContent: true
        }))
            .pipe(opts.languages && opts.languages.length ? i18n_1.processNlsFiles({
            fileHeader: bundledFileHeader,
            languages: opts.languages
        }) : es.through())
            .pipe(gulp.dest(out));
    };
}
exports.optimizeTask = optimizeTask;
function minifyTask(src, sourceMapBaseUrl) {
J
João Moreno 已提交
165
    const esbuild = require('esbuild');
166 167
    const sourceMappingURL = sourceMapBaseUrl ? ((f) => `${sourceMapBaseUrl}/${f.relative}.map`) : undefined;
    return cb => {
168 169
        const minifyCSS = require('gulp-cssnano');
        const sourcemaps = require('gulp-sourcemaps');
170 171
        const jsFilter = filter('**/*.js', { restore: true });
        const cssFilter = filter('**/*.css', { restore: true });
J
João Moreno 已提交
172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
        pump(gulp.src([src + '/**', '!' + src + '/**/*.map']), jsFilter, sourcemaps.init({ loadMaps: true }), es.map((f, cb) => {
            esbuild.build({
                entryPoints: [f.path],
                minify: true,
                sourcemap: 'external',
                outdir: '.',
                platform: 'node',
                target: ['node12.18'],
                write: false
            }).then(res => {
                const jsFile = res.outputFiles.find(f => /\.js$/.test(f.path));
                const sourceMapFile = res.outputFiles.find(f => /\.js\.map$/.test(f.path));
                f.contents = Buffer.from(jsFile.contents);
                f.sourceMap = JSON.parse(sourceMapFile.text);
                cb(undefined, f);
            }, cb);
        }), jsFilter.restore, cssFilter, minifyCSS({ reduceIdents: false }), cssFilter.restore, sourcemaps.mapSources((sourcePath) => {
189 190 191 192 193 194 195 196 197
            if (sourcePath === 'bootstrap-fork.js') {
                return 'bootstrap-fork.orig.js';
            }
            return sourcePath;
        }), sourcemaps.write('./', {
            sourceMappingURL,
            sourceRoot: undefined,
            includeContent: true,
            addComment: true
J
João Moreno 已提交
198
        }), gulp.dest(src + '-min'), (err) => cb(err));
199 200 201
    };
}
exports.minifyTask = minifyTask;