Search code examples
javascriptreactjsgulpbabeljsbrowserify

Adding @wordpress/components dependency increases gulp/browserify build time by 1500%


I'm trying to use WordPress dependencies in my ReactJS Project. For some strange reason importing any component from the @wordpress/components dependency increases my gulp build time from 694ms to 9.42s. This makes it virtually impossible to use a watch with my code.

I'm using babelify / browserify in my build process as follows.

gulfile.js

var argv = require('yargs').argv;
var gulpif = require('gulp-if');
var gulp = require('gulp');
var browserify = require('browserify');         
var babelify = require('babelify');
var source = require('vinyl-source-stream');
var uglify = require('gulp-uglify');
var buffer = require('vinyl-buffer');

var project = {
    scriptSource: './src/react-designer.js',
    outputFile: 'react-designer.js',
    outputDir: './dist/'
}

/**
 * Build an output file. Babelify is used to transform 'jsx' code to JavaScript code. 
 **/
gulp.task("build", function(){
    var options = {
        entries: project.scriptSource,          // Entry point
        extensions: [".js"],                    // consider files with these extensions as modules 
        debug: argv.production ? false : true,  // add resource map at the end of the file or not
        paths: ["./src/"]                       // This allows relative imports in require, with './src/' as root
    };

    var babelifyOpts = {
        sourceMaps: !argv.production,
        presets: [
            "@babel/preset-env",
            "@babel/preset-react"
        ],
        plugins: [
            [ "@babel/plugin-transform-react-jsx" ]
        ]
    }

    return browserify(options)
        .transform( babelify, babelifyOpts )
        .bundle()
        .pipe( source( project.outputFile ) )
        .pipe(gulpif(argv.production, buffer()))    // Stream files
        .pipe(gulpif(argv.production, uglify()))
        .pipe(gulp.dest("./dist/"));
});

package.json

{
    "version": "1.0.0-alpha.0",
    "description": "",
    "author": "NOKNOK Studios",
    "files": [
        "dist/"
    ],
    "dependencies": {
        "@wordpress/components": "^17.0.0",
        "ntc": "^0.0.1",
        "react": "^17.0.2"
    },
    "private": true,
    "devDependencies": {
        "@babel/core": "^7.15.5",
        "@babel/plugin-transform-react-jsx": "^7.14.9",
        "@babel/plugin-transform-react-jsx-self": "^7.14.9",
        "@babel/preset-env": "^7.15.6",
        "@babel/preset-react": "^7.14.5",
        "babelify": "^10.0.0",
        "browserify": "^17.0.0",
        "git": "^0.1.5",
        "gulp": "^4.0.2",
        "gulp-bump": "^3.2.0",
        "gulp-filter": "^7.0.0",
        "gulp-sass": "^5.0.0",
        "gulp-sourcemaps": "^3.0.0",
        "gulp-tag-version": "^1.3.1",
        "gulp-uglify": "^3.0.2",
        "node-sass": "^6.0.1",
        "sass": "^1.41.0",
        "vinyl-buffer": "^1.0.1",
        "vinyl-source-stream": "^2.0.0"
    }
}

react-designer.js

import Component from 'react';
import { Button } from '@wordpress/components';

class Designer extends Component {


    render() {
        return <Button>Click Me!</Button>;
    }

}

I realize that the increase in build time is likely due to the number of dependencies used by @wordpress/components. I'd rather not swap out this dependency if possible.

Any advice on how I can optimize my build process to be to run in under 2s ?


Solution

  • Turns out I'm an idiot and Watchify is "practically a must" since it caches dependencies between watched builds. Using a native gulp watch was my problem.

    Updated gulpfile.js

    var argv        = require( 'yargs' ).argv;
    var gulpif      = require( 'gulp-if' );
    var gulp        = require( 'gulp' );
    var watchify    = require( 'watchify' );
    var browserify  = require( 'browserify');         
    var babelify    = require( 'babelify' );
    var source      = require( 'vinyl-source-stream' );
    var uglify      = require( 'gulp-uglify' );
    var buffer      = require( 'vinyl-buffer' );
    var assign      = require( 'lodash.assign' );
    var sourcemaps = require('gulp-sourcemaps');
    var log         = require( 'gulplog' )
    
    var project = {
        sourceDir: './src/',
        scriptSource: './src/react-designer.js',
        outputFile: 'react-designer.js',
        outputDir: './dist/'
    }
    
    var options = assign({}, watchify.args, {
        entries: project.scriptSource,          // Entry point
        extensions: [ ".js" ],                  // consider files with these extensions as modules 
        debug: argv.production ? false : true,  // add resource map at the end of the file or not
        paths: [ project.sourceDir ],           // This allows relative imports in require, with './src/' as root
    });
    
    var babelifyOpts = {
        sourceMaps: argv.production ? false : true,
        presets: [
            "@babel/preset-env",
            "@babel/preset-react"
        ],
        plugins: [
            [ 
                "@babel/plugin-transform-react-jsx"
            ]
        ]
    }
    
    function bundle( bundler ) {
        bundler = bundler.transform( babelify, babelifyOpts )
    
        bundler.on( 'update', () => rebundle( bundler) );
        bundler.on( 'log', log.info );
    
        return rebundle( bundler );
    }
    
    function rebundle( bundler ) {
        return bundler
            .bundle()
            .on('error', log.error.bind(log, 'Browserify Error'))
    
            .pipe( source( project.outputFile ) )
            .pipe( buffer() )    // Stream files
            .pipe( gulpif( ! argv.production, sourcemaps.init( { loadMaps: true } ) ) ) // loads map from browserify file
            .pipe( gulpif( argv.production, uglify() ) )
    
            .pipe( gulpif( ! argv.production, sourcemaps.write( './' ) ) ) // writes .map file
            .pipe( gulp.dest( project.outputDir ) );
    }
    
    gulp.task( 'build:js', () => bundle( browserify( options ) ) );
    gulp.task( 'watch:js', () => bundle( watchify( browserify( options ) ) ) );