Grunt CLI вылетает при попытке скомпилировать bootstrap.less - PullRequest
0 голосов
/ 01 июня 2018

Я некоторое время работал над своим Mac в веб-приложении, компилируя с помощью Grunt на моем Mac - без проблем с компиляцией.

Я просто настроил проект на новом ультрабуке (Acer Spin5, i5, 8-гигабайтная оперативная память, небольшая, но способная), но если я не удаляю почти все записи в bootstrap. Если компиляция не удалась.

Я начинаю свою компиляцию, используя: grunt dev -env = dev -f--verbose

Ошибка, которую я получаю:

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory

Я читал о настройке параметра "max-old-space-size" для узла, но я не совсемуверен, как настроить его в моем gruntfile.js или package.json (я не очень хорошо разбираюсь в Grunt / Node в целом).

Если я удаляю все, кроме первой пары импортов в начальной загрузкеЕсли компиляция не завершится, как ожидалось.

Мой gruntfile тоже немного чудовищный, слишком длинный, чтобы публиковать его; (ниже я удалил ненужные части:

module.exports = function (grunt) {
'use strict';

// Force use of Unix newlines
grunt.util.linefeed = '\n';

RegExp.quote = function (string) {
    return string.replace(/[-\\^$*+?.()|[\]{}]/g, '\\$&');
};

var fs = require('fs');
var path = require('path');
var npmShrinkwrap = require('npm-shrinkwrap');
var generateGlyphiconsData = require('./grunt/bs-glyphicons-data-generator.js');
var BsLessdocParser = require('./grunt/bs-lessdoc-parser.js');
var getLessVarsData = function () {
    var filePath = path.join(__dirname, 'less/variables.less');
    var fileContent = fs.readFileSync(filePath, {
        encoding: 'utf8'
    });
    var parser = new BsLessdocParser(fileContent);
    return {
        sections: parser.parseFile()
    };
};
var generateRawFiles = require('./grunt/bs-raw-files-generator.js');
var generateCommonJSModule = require('./grunt/bs-commonjs-generator.js');
var configBridge = grunt.file.readJSON('./grunt/configBridge.json', {
    encoding: 'utf8'
});

Object.keys(configBridge.paths).forEach(function (key) {
    configBridge.paths[key].forEach(function (val, i, arr) {
        arr[i] = path.join('./docs/assets', val);
    });
});

grunt.loadNpmTasks('grunt-include-replace-more');
grunt.loadNpmTasks('grunt-dev-prod-switch');
grunt.loadNpmTasks('grunt-minify-html');
grunt.loadNpmTasks('grunt-symlink');

// Project configuration.
grunt.initConfig({

    // Metadata.
    pkg: grunt.file.readJSON('package.json'),
    banner: '/*!\n' +
        ' * Plenty.rdthree.com v<%= pkg.version %> (<%= pkg.homepage %>)\n' +
        ' * Copyright 2015-<%= grunt.template.today("yyyy") %> <%= pkg.author %>\n' +
        ' * Licensed under <%= pkg.license.type %> (<%= pkg.license.url %>)\n' +
        ' */\n',
    jqueryCheck: configBridge.config.jqueryCheck.join('\n'),
    jqueryVersionCheck: configBridge.config.jqueryVersionCheck.join('\n'),

    // Task configuration.
    clean: {
        dist: 'dist',
        docs: 'docs/dist',
        pageSpecificJS: ['dist/js/pageScripts/*.js', '!dist/js/pageScripts/*.min.js'],
        pageSpecificCSS: ['dist/css/*.css', '!dist/css/*.min.css']
    },

    jshint: {
        options: {
            jshintrc: 'js/.jshintrc'
        },
        grunt: {
            options: {
                jshintrc: 'grunt/.jshintrc'
            },
            src: ['Gruntfile.js', 'grunt/*.js']
        },
        core: {
            src: 'js/*.js'
        },
        test: {
            options: {
                jshintrc: 'js/tests/unit/.jshintrc'
            },
            src: 'js/tests/unit/*.js'
        },
        assets: {
            src: ['docs/assets/js/src/*.js', 'docs/assets/js/*.js', '!docs/assets/js/*.min.js']
        }
    },

    jscs: {
        options: {
            config: 'js/.jscsrc'
        },
        grunt: {
            src: '<%= jshint.grunt.src %>'
        },
        core: {
            src: '<%= jshint.core.src %>'
        },
        test: {
            src: '<%= jshint.test.src %>'
        },
        assets: {
            options: {
                requireCamelCaseOrUpperCaseIdentifiers: null
            },
            src: '<%= jshint.assets.src %>'
        }
    },

    symlink: {
        prod: {
            dest: 'dist/prod',
            relativeSrc: '../dist',
            options: {
                type: 'dir'
            } // 'file' by default 
        },
        perf: {
            dest: 'dist/perf',
            relativeSrc: '../dist',
            options: {
                type: 'dir'
            } // 'file' by default 
        },
    },

    concat: {
        bootstrap: {
            options: {
                banner: '<%= banner %>\n<%= jqueryCheck %>\n<%= jqueryVersionCheck %>',
                stripBanners: false
            },
            src: [
                'js/vendor/jquery-migrate-3.0.0.js',
                'js/bootstrap/transition.js',
                'js/bootstrap/alert.js',
                'js/bootstrap/button.js',
                'js/bootstrap/carousel.js',
                'js/bootstrap/collapse.js',
                'js/bootstrap/dropdown.js',
                'js/bootstrap/modal.js',
                'js/bootstrap/tooltip.js',
                'js/bootstrap/popover.js',
                'js/bootstrap/tab.js'
            ],
            dest: 'dist/js/<%= pkg.name %>.js'
        }
    },
    minifyHtml: {
        options: {
            cdata: true
        },
        dist: {
            files: [{
                expand: true,
                cwd: 'dist',
                src: ['*.html'],
                dest: 'dist'
            }]
        }
    },
    dev_prod_switch: {
        options: {
            environment: grunt.option('env') || 'dev',
            env_char: '#',
            env_block_dev: 'env:dev',
            env_block_prod: 'env:prod'
        },
        dynamic_mappings: {
            files: [{
                expand: true,
                cwd: 'dist',
                src: ['*.html', 'mobile/*.html', 'js/includes.js', 'mobile/js/mobile.js', 'js/includes.min.js', 'js/pageScripts/setup*.js', 'js/touch/touch-support*.js'],
                dest: 'dist'
            }]
        }
    },
    uglify: {
        options: {
            preserveComments: 'false'
        },
        core: {
            src: '<%= concat.bootstrap.dest %>',
            dest: 'dist/js/<%= pkg.name %>.min.js'
        },
        includes: {
            src: 'dist/js/includes.js',
            dest: 'dist/js/includes.min.js'
        },
        mobile: {
            src: 'dist/mobile/js/mobile.js',
            dest: 'dist/mobile/js/mobile.min.js'
        },
        customize: {
            src: configBridge.paths.customizerJs,
            dest: 'docs/assets/js/customize.min.js'
        },
        docsJs: {
            src: configBridge.paths.docsJs,
            dest: 'docs/assets/js/docs.min.js'
        },
        dashboard: {
            src: 'dist/js/pageScripts/dashboard.js',
            dest: 'dist/js/pageScripts/dashboard.min.js'
        },
        setup: {
            src: 'dist/js/pageScripts/setup.js',
            dest: 'dist/js/pageScripts/setup.min.js'
        },
        billing: {
            src: 'dist/js/pageScripts/billing.js',
            dest: 'dist/js/pageScripts/billing.min.js'
        },
        schedule: {
            src: 'dist/js/pageScripts/schedule.js',
            dest: 'dist/js/pageScripts/schedule.min.js'
        },
    },
    qunit: {
        options: {
            inject: 'js/tests/unit/phantom.js'
        },
        files: 'js/tests/index.html'
    },

    less: {
        compileCore: {
            options: {
                strictMath: false,
                sourceMap: false,
                outputSourceFiles: true,
                sourceMapURL: '<%= pkg.name %>.css.map',
                sourceMapFilename: 'dist/css/<%= pkg.name %>.css.map'
            },
            src: 'less/bootstrap.less',
            dest: 'dist/css/<%= pkg.name %>.css'
        },
    },

    autoprefixer: {
        options: {
            browsers: configBridge.config.autoprefixerBrowsers
        },
        core: {
            options: {
                map: true
            },
            src: 'dist/css/<%= pkg.name %>.css'
        },
        theme: {
            options: {
                map: true
            },
            src: 'dist/css/<%= pkg.name %>-theme.css'
        },
        plenty: {
            options: {
                map: true
            },
            src: 'dist/css/plenty.css'
        },
        docs: {
            src: ['docs/assets/css/anchor.css', 'docs/assets/css/src/docs.css']
        },
        examples: {
            expand: true,
            cwd: 'docs/examples/',
            src: ['**/*.css'],
            dest: 'docs/examples/'
        }
    },

    csslint: {
        options: {
            csslintrc: 'less/.csslintrc'
        },
        dist: [
            'dist/css/bootstrap.css',
            'dist/css/bootstrap-theme.css'
        ],
        examples: [
            'docs/examples/**/*.css'
        ],
        docs: {
            options: {
                ids: false,
                'overqualified-elements': false
            },
            src: 'docs/assets/css/src/docs.css'
        }
    },

    cssmin: {
        options: {
            // TODO: disable `zeroUnits` optimization once clean-css 3.2 is released
            //    and then simplify the fix for https://github.com/twbs/bootstrap/issues/14837 accordingly
            compatibility: 'ie8',
            keepSpecialComments: '*',
            advanced: false
        },
        minifyCore: {
            src: 'dist/css/<%= pkg.name %>.css',
            dest: 'dist/css/<%= pkg.name %>.min.css'
        },
        minifyTheme: {
            src: 'dist/css/<%= pkg.name %>-theme.css',
            dest: 'dist/css/<%= pkg.name %>-theme.min.css'
        },
        minifyPlenty: {
            src: 'dist/css/plenty.css',
            dest: 'dist/css/plenty.min.css'
        },
        minifySetup: {
            src: 'dist/css/setup.css',
            dest: 'dist/css/setup.min.css'
        },
        minifyDashboard: {
            src: 'dist/css/dashboard.css',
            dest: 'dist/css/dashboard.min.css'
        },
    },

    usebanner: {
        options: {
            position: 'top',
            banner: '<%= banner %>'
        },
        files: {
            src: 'dist/css/*.css'
        }
    },

    csscomb: {
        options: {
            config: 'less/.csscomb.json'
        },
        dist: {
            expand: true,
            cwd: 'dist/css/',
            src: ['*.css', '!*.min.css'],
            dest: 'dist/css/'
        },
        examples: {
            expand: true,
            cwd: 'docs/examples/',
            src: '**/*.css',
            dest: 'docs/examples/'
        },
        docs: {
            src: 'docs/assets/css/src/docs.css',
            dest: 'docs/assets/css/src/docs.css'
        }
    },

    copy: {
        fonts: {
            expand: true,
            src: 'fonts/*',
            dest: 'dist/'
        },
        docs: {
            expand: true,
            cwd: 'dist/',
            src: [
                '**/*'
            ],
            dest: 'docs/dist/'
        },
        img: {
            cwd: 'img', // set working folder / root to copy
            src: '**/*', // copy all files and subfolders
            dest: 'dist/img', // destination folder
            expand: true // required when using cwd
        },
        ajax: {
            cwd: 'ajax', // set working folder / root to copy
            src: '**/*', // copy all files and subfolders
            dest: 'dist/ajax', // destination folder
            expand: true // required when using cwd
        },
    },

    includereplacemore: {
        your_target: {
            options: {
                // Task-specific options go here.
            },
            // Files to perform replacements and includes with
            src: ['*.html', 'ajax/*.html', "mobile/*.html"],
            // Destination directory to copy files to
            dest: 'dist/'
        }
    },

    connect: {
        server: {
            options: {
                port: 3000,
                base: '.'
            }
        }
    },

    jekyll: {
        options: {
            config: '_config.yml'
        },
        docs: {},
        github: {
            options: {
                raw: 'github: true'
            }
        }
    },

    jade: {
        options: {
            pretty: true,
            data: getLessVarsData
        },
        customizerVars: {
            src: 'docs/_jade/customizer-variables.jade',
            dest: 'docs/_includes/customizer-variables.html'
        },
        customizerNav: {
            src: 'docs/_jade/customizer-nav.jade',
            dest: 'docs/_includes/nav/customize.html'
        }
    },

    htmllint: {
        options: {
            ignore: [
                'Attribute "autocomplete" not allowed on element "button" at this point.',
                'Attribute "autocomplete" not allowed on element "input" at this point.',
                'Element "img" is missing required attribute "src".'
            ]
        },
        src: '_gh_pages/**/*.html'
    },

    watch: {
        src: {
            files: '<%= jshint.core.src %>',
            tasks: ['jshint:src', 'qunit', 'concat']
        },
        test: {
            files: '<%= jshint.test.src %>',
            tasks: ['jshint:test', 'qunit']
        },
        less: {
            files: 'less/**/*.less',
            tasks: 'less'
        }
    },

    sed: {
        versionNumber: {
            pattern: (function () {
                var old = grunt.option('oldver');
                return old ? RegExp.quote(old) : old;
            })(),
            replacement: grunt.option('newver'),
            recursive: true
        }
    },

    'saucelabs-qunit': {
        all: {
            options: {
                build: process.env.TRAVIS_JOB_ID,
                throttled: 10,
                maxRetries: 3,
                maxPollRetries: 4,
                urls: ['http://127.0.0.1:3000/js/tests/index.html?hidepassed'],
                browsers: grunt.file.readYAML('grunt/sauce_browsers.yml')
            }
        }
    },

    exec: {
        npmUpdate: {
            command: 'npm update'
        }
    },

    compress: {
        main: {
            options: {
                archive: 'bootstrap-<%= pkg.version %>-dist.zip',
                mode: 'zip',
                level: 9,
                pretty: true
            },
            files: [{
                expand: true,
                cwd: 'dist/',
                src: ['**'],
                dest: 'bootstrap-<%= pkg.version %>-dist'
            }]
        }
    }

});


// These plugins provide necessary tasks.
require('load-grunt-tasks')(grunt, {
    scope: 'devDependencies'
});
require('time-grunt')(grunt);

// Docs HTML validation task
grunt.registerTask('validate-html', ['jekyll:docs', 'htmllint']);

var runSubset = function (subset) {
    return !process.env.TWBS_TEST || process.env.TWBS_TEST === subset;
};
var isUndefOrNonZero = function (val) {
    return val === undefined || val !== '0';
};

// Test task.
var testSubtasks = [];
// Skip core tests if running a different subset of the test suite
if (runSubset('core') &&
    // Skip core tests if this is a Savage build
    process.env.TRAVIS_REPO_SLUG !== 'twbs-savage/bootstrap') {
    testSubtasks = testSubtasks.concat(['dist-css', 'dist-js', 'csslint:dist', 'test-js', 'docs']);
}
// Skip HTML validation if running a different subset of the test suite
if (runSubset('validate-html') &&
    // Skip HTML5 validator on Travis when [skip validator] is in the commit message
    isUndefOrNonZero(process.env.TWBS_DO_VALIDATOR)) {
    testSubtasks.push('validate-html');
}
// Only run Sauce Labs tests if there's a Sauce access key
if (typeof process.env.SAUCE_ACCESS_KEY !== 'undefined' &&
    // Skip Sauce if running a different subset of the test suite
    runSubset('sauce-js-unit') &&
    // Skip Sauce on Travis when [skip sauce] is in the commit message
    isUndefOrNonZero(process.env.TWBS_DO_SAUCE)) {
    testSubtasks.push('connect');
    testSubtasks.push('saucelabs-qunit');
}
grunt.registerTask('test', testSubtasks);
grunt.registerTask('test-js', ['jshint:core', 'jshint:test', 'jshint:grunt', 'jscs:core', 'jscs:test', 'jscs:grunt', 'qunit']);

// JS distribution task.
grunt.registerTask('dist-js', ['concat', 'uglify:core', 'commonjs', 'includereplacemore']);

// JS minify page specific scripts
grunt.registerTask('uglify-pageScripts', ['uglify:dashboard', 'uglify:setup', 'uglify:billing', 'uglify:schedule', 'uglify:inventory', 'uglify:grainMarketing', 'uglify:map', 'uglify:organization', 'uglify:plans', 'uglify:schedule', 'uglify:services', 'uglify:servicessetup', 'uglify:timeentry', 'uglify:signin', 'uglify:characterPatterns', "uglify:mobile"]);

grunt.registerTask('uglify-touchScripts', ['uglify:touch_dashboard', 'uglify:touch_setup', 'uglify:touch_billing', 'uglify:touch_schedule', 'uglify:touch_inventory', 'uglify:touch_grainMarketing', 'uglify:touch_map', 'uglify:touch_organization', 'uglify:touch_plans', 'uglify:touch_schedule', 'uglify:touch_services', 'uglify:touch_servicessetup', 'uglify:touch_timeentry', 'uglify:touch_support']);

grunt.registerTask('uglify-mobile-pageScripts', ['uglify:mobile_activityList', 'uglify:mobile_addActivity', 'uglify:mobile_addPhotos', 'uglify:mobile_contactList', 'uglify:mobile_getPrepared', 'uglify:mobile_notes', 'uglify:mobile_schedule', 'uglify:mobile_taskDetail', 'uglify:mobile_taskInProgress', 'uglify:mobile_requirements', 'uglify:mobile_collect', 'uglify:mobile_viewPhoto', 'uglify:mobile_returnProducts', 'uglify:mobile_returnProduct']);

// Compile Page CSS
grunt.registerTask('compile-pageCSS', ['less:compilePlenty', 'less:compileSetup', 'less:compileDashboard', 'less:compileField', 'less:compileSignin', 'less:compileMobile']);

// Mimify CSS
grunt.registerTask('minify-pageCSS', ['cssmin:minifyCore', 'cssmin:minifyTheme', 'cssmin:minifyPlenty', 'cssmin:minifyDashboard', 'cssmin:minifySetup', 'cssmin:minifyField', 'cssmin:minifySignin', 'cssmin:minifyMobile']);

// JS Default Task.
grunt.registerTask('default-js', ['concat', 'uglify:core', 'uglify:includes', 'uglify:mobile', 'uglify-pageScripts', 'uglify-touchScripts', 'uglify-mobile-pageScripts', 'commonjs', 'includereplacemore']);

// CSS distribution task.
grunt.registerTask('less-compile', ['less:compileCore', 'less:compileTheme', 'compile-pageCSS', 'minify-pageCSS']);

grunt.registerTask('dist-css', ['less-compile', 'autoprefixer:core', 'autoprefixer:theme', 'autoprefixer:plenty', 'usebanner', 'csscomb:dist']);

// create symlinks
grunt.registerTask("symlinks", ['symlink:prod', 'symlink:perf']);

// Full distribution task.
grunt.registerTask('dev', ['clean:dist', 'dist-css', 'copy:fonts', 'copy:fontAwesome', 'symlinks', 'copy:weatherIcons', 'copy:intlTelInput', 'copy:phoneLib', 'copy:jquery311', 'copy:charPatterns', 'copy:pageScripts', 'copy:outdatedbrowser', 'copy:flatPickr', 'copy:hammertime', 'copy:hammerjs', 'copy:initialize', 'copy:touchsupport', 'copy:dropzone', 'copy:mobile', 'copy:xeditable', 'copy:manifest', 'copy:htaccess', 'copy:img', 'copy:ajax', 'dist-js', 'dev_prod_switch', 'minifyHtml']);

// Default task.
grunt.registerTask('prod', ['clean:dist', 'dist-css', 'copy:fonts', 'copy:fontAwesome', 'symlinks', 'copy:weatherIcons', 'copy:intlTelInput', 'copy:phoneLib', 'copy:jquery311', 'copy:charPatterns', 'copy:pageScripts', 'copy:outdatedbrowser', 'copy:flatPickr', 'copy:hammertime', 'copy:hammerjs', 'copy:initialize', 'copy:touchsupport', 'copy:dropzone', 'copy:mobile', 'copy:xeditable', 'copy:manifest', 'copy:htaccess', 'copy:img', 'copy:ajax', 'default-js', 'clean:pageSpecificJS', 'clean:pageSpecificCSS', 'dev_prod_switch', 'minifyHtml']);

// Version numbering task.
// grunt change-version-number --oldver=A.B.C --newver=X.Y.Z
// This can be overzealous, so its changes should always be manually reviewed!
grunt.registerTask('change-version-number', 'sed');

grunt.registerTask('build-glyphicons-data', function () {
    generateGlyphiconsData.call(this, grunt);
});

// task for building customizer
grunt.registerTask('build-customizer', ['build-customizer-html', 'build-raw-files']);
grunt.registerTask('build-customizer-html', 'jade');
grunt.registerTask('build-raw-files', 'Add scripts/less files to customizer.', function () {
    var banner = grunt.template.process('<%= banner %>');
    generateRawFiles(grunt, banner);
});

grunt.registerTask('commonjs', 'Generate CommonJS entrypoint module in dist dir.', function () {
    var srcFiles = grunt.config.get('concat.bootstrap.src');
    var destFilepath = 'dist/js/npm.js';
    generateCommonJSModule(grunt, srcFiles, destFilepath);
});

// Docs task.
grunt.registerTask('docs-css', ['autoprefixer:docs', 'autoprefixer:examples', 'csscomb:docs', 'csscomb:examples', 'cssmin:docs']);
grunt.registerTask('lint-docs-css', ['csslint:docs', 'csslint:examples']);
grunt.registerTask('docs-js', ['uglify:docsJs', 'uglify:customize']);
grunt.registerTask('lint-docs-js', ['jshint:assets', 'jscs:assets']);
grunt.registerTask('docs', ['docs-css', 'lint-docs-css', 'docs-js', 'lint-docs-js', 'clean:docs', 'copy:docs', 'build-glyphicons-data', 'build-customizer']);

grunt.registerTask('prep-release', ['jekyll:github', 'compress']);

// Task for updating the cached npm packages used by the Travis build (which are controlled by test-infra/npm-shrinkwrap.json).
// This task should be run and the updated file should be committed whenever Bootstrap's dependencies change.
grunt.registerTask('update-shrinkwrap', ['exec:npmUpdate', '_update-shrinkwrap']);
grunt.registerTask('_update-shrinkwrap', function () {
    var done = this.async();
    npmShrinkwrap({
        dev: true,
        dirname: __dirname
    }, function (err) {
        if (err) {
            grunt.fail.warn(err);
        }
        var dest = 'test-infra/npm-shrinkwrap.json';
        fs.renameSync('npm-shrinkwrap.json', dest);
        grunt.log.writeln('File ' + dest.cyan + ' updated.');
        done();
    });
});

};

Любая помощь приветствуется - спасибо

1 Ответ

0 голосов
/ 04 июня 2018

Я разделил файл bootstrap.less на два файла, которые решили проблему

...