Skip to content

Commit

Permalink
Build: Add building/watching support to Gutenberg packages
Browse files Browse the repository at this point in the history
  • Loading branch information
youknowriad committed May 11, 2018
1 parent d70ec18 commit 7faa1be
Show file tree
Hide file tree
Showing 6 changed files with 239 additions and 3 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Directories/files that may be generated by this project
build
build-module
coverage
/hooks
node_modules
Expand Down
142 changes: 142 additions & 0 deletions bin/packages/build.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/**
* script to build WordPress packages into `build/` directory.
*
* Example:
* node ./scripts/build.js
*/

/**
* External Dependenceis
*/
const fs = require( 'fs' );
const path = require( 'path' );
const glob = require( 'glob' );
const babel = require( 'babel-core' );
const chalk = require( 'chalk' );
const mkdirp = require( 'mkdirp' );

/**
* Internal dependencies
*/
const getPackages = require( './get-packages' );

/**
* Module Constants
*/
const PACKAGES_DIR = path.resolve( __dirname, '../../packages' );
const SRC_DIR = 'src';
const BUILD_DIR = {
main: 'build',
module: 'build-module',
};
const DONE = chalk.reset.inverse.bold.green( ' DONE ' );

/**
* Babel Configuration
*/
const babelDefaultConfig = require( '@wordpress/babel-preset-default' );
babelDefaultConfig.babelrc = false;
const presetEnvConfig = babelDefaultConfig.presets[ 0 ][ 1 ];
const babelConfigs = {
main: Object.assign(
{},
babelDefaultConfig,
{ presets: [
[ 'env', Object.assign(
{},
presetEnvConfig,
{ modules: 'commonjs' },
) ],
] }
),
module: babelDefaultConfig,
};

/**
* Get the package name for a specified file
*
* @param {string} file File name
* @return {string} Package name
*/
function getPackageName( file ) {
return path.relative( PACKAGES_DIR, file ).split( path.sep )[ 0 ];
}

/**
* Get Build Path for a specified file
*
* @param {string} file File to build
* @param {string} buildFolder Output folder
* @return {string} Build path
*/
function getBuildPath( file, buildFolder ) {
const pkgName = getPackageName( file );
const pkgSrcPath = path.resolve( PACKAGES_DIR, pkgName, SRC_DIR );
const pkgBuildPath = path.resolve( PACKAGES_DIR, pkgName, buildFolder );
const relativeToSrcPath = path.relative( pkgSrcPath, file );
return path.resolve( pkgBuildPath, relativeToSrcPath );
}

/**
* Build a file for the required environments (node and ES5)
*
* @param {string} file File path to build
* @param {boolean} silent Show logs
*/
function buildFile( file, silent ) {
buildFileFor( file, silent, 'main' );
buildFileFor( file, silent, 'module' );
}

/**
* Build a file for a specific environment
*
* @param {string} file File path to build
* @param {boolean} silent Show logs
* @param {string} environment Dist environment (node or es5)
*/
function buildFileFor( file, silent, environment ) {
const buildDir = BUILD_DIR[ environment ];
const destPath = getBuildPath( file, buildDir );
const babelOptions = babelConfigs[ environment ];

mkdirp.sync( path.dirname( destPath ) );
const transformed = babel.transformFileSync( file, babelOptions ).code;
fs.writeFileSync( destPath, transformed );
if ( ! silent ) {
process.stdout.write(
chalk.green( ' \u2022 ' ) +
path.relative( PACKAGES_DIR, file ) +
chalk.green( ' \u21D2 ' ) +
path.relative( PACKAGES_DIR, destPath ) +
'\n'
);
}
}

/**
* Build the provided package path
*
* @param {string} packagePath absolute package path
*/
function buildPackage( packagePath ) {
const srcDir = path.resolve( packagePath, SRC_DIR );
const files = glob.sync( srcDir + '/**/*.js', { nodir: true } )
.filter( ( file ) => ! /\.test\.js/.test( file ) );

process.stdout.write( `${ path.basename( packagePath ) }\n` );

files.forEach( ( file ) => buildFile( file, true ) );
process.stdout.write( `${ DONE }\n` );
}

const files = process.argv.slice( 2 );

if ( files.length ) {
files.forEach( buildFile );
} else {
process.stdout.write( chalk.inverse( '>> Building packages \n' ) );
getPackages()
.forEach( buildPackage );
process.stdout.write( '\n' );
}
24 changes: 24 additions & 0 deletions bin/packages/get-packages.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* External Dependenceis
*/
const fs = require( 'fs' );
const path = require( 'path' );

/**
* Module Constants
*/
const PACKAGES_DIR = path.resolve( __dirname, '../../packages' );

/**
* Returns the absolute path of all WordPress packages
*
* @return {Array} Package paths
*/
function getPackages() {
return fs
.readdirSync( PACKAGES_DIR )
.map( ( file ) => path.resolve( PACKAGES_DIR, file ) )
.filter( ( f ) => fs.lstatSync( path.resolve( f ) ).isDirectory() );
}

module.exports = getPackages;
66 changes: 66 additions & 0 deletions bin/packages/watch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/**
* External dependencies
*/
const fs = require( 'fs' );
const { execSync } = require( 'child_process' );
const path = require( 'path' );
const chalk = require( 'chalk' );

/**
* Internal dependencies
*/
const getPackages = require( './get-packages' );

const BUILD_CMD = `node ${ path.resolve( __dirname, './build.js' ) }`;

let filesToBuild = new Map();

const exists = ( filename ) => {
try {
return fs.statSync( filename ).isFile();
} catch ( e ) {}
return false;
};
const rebuild = ( filename ) => filesToBuild.set( filename, true );

getPackages().forEach( ( p ) => {
const srcDir = path.resolve( p, 'src' );
try {
fs.accessSync( srcDir, fs.F_OK );
fs.watch( path.resolve( p, 'src' ), { recursive: true }, ( event, filename ) => {
const filePath = path.resolve( srcDir, filename );

if ( ( event === 'change' || event === 'rename' ) && exists( filePath ) ) {
// eslint-disable-next-line no-console
console.log( chalk.green( '->' ), `${ event }: ${ filename }` );
rebuild( filePath );
} else {
const buildFile = path.resolve( srcDir, '..', 'build', filename );
try {
fs.unlinkSync( buildFile );
process.stdout.write(
chalk.red( ' \u2022 ' ) +
path.relative( path.resolve( srcDir, '..', '..' ), buildFile ) +
' (deleted)' +
'\n'
);
} catch ( e ) {}
}
} );
} catch ( e ) {
// doesn't exist
}
} );

setInterval( () => {
const files = Array.from( filesToBuild.keys() );
if ( files.length ) {
filesToBuild = new Map();
try {
execSync( `${ BUILD_CMD } ${ files.join( ' ' ) }`, { stdio: [ 0, 1, 2 ] } );
} catch ( e ) {}
}
}, 100 );

// eslint-disable-next-line no-console
console.log( chalk.red( '->' ), chalk.cyan( 'Watching for changes...' ) );
6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -121,12 +121,14 @@
},
"scripts": {
"prebuild": "check-node-version --package",
"build": "cross-env NODE_ENV=production webpack",
"build:packages": "rimraf ./packages/*/build ./packages/*/build-module && node ./bin/packages/build.js",
"build": "npm run build:packages && cross-env NODE_ENV=production webpack",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"lint-php": "docker-compose run --rm composer run-script lint",
"predev": "check-node-version --package",
"dev": "cross-env webpack --watch",
"dev": "npm run build:packages && concurrently \"cross-env webpack --watch\" \"npm run dev:packages\"",
"dev:packages": "node ./bin/packages/watch.js",
"test": "npm run lint && npm run test-unit",
"test-php": "npm run lint-php && npm run test-unit-php",
"ci": "concurrently \"npm run lint && npm run build\" \"npm run test-unit:coverage-ci\"",
Expand Down
3 changes: 2 additions & 1 deletion packages/date/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
"bugs": {
"url": "https://github.com/WordPress/gutenberg/issues"
},
"main": "src/index.js",
"main": "build/index.js",
"module": "build-module/index.js",
"dependencies": {
"moment": "2.22.1",
"moment-timezone": "0.5.16"
Expand Down

0 comments on commit 7faa1be

Please sign in to comment.