Skip to content

Commit 5c38808

Browse files
aduthtalldan
andauthored
Build Tooling: Optimize build by spawning worker pool (#15230)
* Build Tooling: Create worker pool for build * Build Tooling: Define build concurrency explicitly * Revert "Build Tooling: Define build concurrency explicitly" This reverts commit 4338f9e. * Build Tooling: Implement build files sourcing as stream * Build Tooling: Reinstate error handling to build script * Build Tooling: Log build error to stderr Co-Authored-By: Daniel Richards <daniel.p.richards@gmail.com> * Build: Assign non-zero exit code on build error Co-Authored-By: Daniel Richards <talldan@users.noreply.github.com>
1 parent 1a6660c commit 5c38808

File tree

4 files changed

+327
-214
lines changed

4 files changed

+327
-214
lines changed

bin/packages/build-worker.js

+159
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
/**
2+
* External dependencies
3+
*/
4+
const { promisify } = require( 'util' );
5+
const fs = require( 'fs' );
6+
const path = require( 'path' );
7+
const babel = require( '@babel/core' );
8+
const makeDir = require( 'make-dir' );
9+
const sass = require( 'node-sass' );
10+
const postcss = require( 'postcss' );
11+
12+
/**
13+
* Internal dependencies
14+
*/
15+
const getBabelConfig = require( './get-babel-config' );
16+
17+
/**
18+
* Path to packages directory.
19+
*
20+
* @type {string}
21+
*/
22+
const PACKAGES_DIR = path.resolve( __dirname, '../../packages' );
23+
24+
/**
25+
* Mapping of JavaScript environments to corresponding build output.
26+
*
27+
* @type {Object}
28+
*/
29+
const JS_ENVIRONMENTS = {
30+
main: 'build',
31+
module: 'build-module',
32+
};
33+
34+
/**
35+
* Promisified fs.readFile.
36+
*
37+
* @type {Function}
38+
*/
39+
const readFile = promisify( fs.readFile );
40+
41+
/**
42+
* Promisified fs.writeFile.
43+
*
44+
* @type {Function}
45+
*/
46+
const writeFile = promisify( fs.writeFile );
47+
48+
/**
49+
* Promisified sass.render.
50+
*
51+
* @type {Function}
52+
*/
53+
const renderSass = promisify( sass.render );
54+
55+
/**
56+
* Get the package name for a specified file
57+
*
58+
* @param {string} file File name
59+
* @return {string} Package name
60+
*/
61+
function getPackageName( file ) {
62+
return path.relative( PACKAGES_DIR, file ).split( path.sep )[ 0 ];
63+
}
64+
65+
/**
66+
* Get Build Path for a specified file.
67+
*
68+
* @param {string} file File to build
69+
* @param {string} buildFolder Output folder
70+
* @return {string} Build path
71+
*/
72+
function getBuildPath( file, buildFolder ) {
73+
const pkgName = getPackageName( file );
74+
const pkgSrcPath = path.resolve( PACKAGES_DIR, pkgName, 'src' );
75+
const pkgBuildPath = path.resolve( PACKAGES_DIR, pkgName, buildFolder );
76+
const relativeToSrcPath = path.relative( pkgSrcPath, file );
77+
return path.resolve( pkgBuildPath, relativeToSrcPath );
78+
}
79+
80+
/**
81+
* Object of build tasks per file extension.
82+
*
83+
* @type {Object<string,Function>}
84+
*/
85+
const BUILD_TASK_BY_EXTENSION = {
86+
async '.scss'( file ) {
87+
const outputFile = getBuildPath( file.replace( '.scss', '.css' ), 'build-style' );
88+
const outputFileRTL = getBuildPath( file.replace( '.scss', '-rtl.css' ), 'build-style' );
89+
90+
const [ , contents ] = await Promise.all( [
91+
makeDir( path.dirname( outputFile ) ),
92+
readFile( file, 'utf8' ),
93+
] );
94+
95+
const builtSass = await renderSass( {
96+
file,
97+
includePaths: [ path.resolve( __dirname, '../../assets/stylesheets' ) ],
98+
data: (
99+
[
100+
'colors',
101+
'breakpoints',
102+
'variables',
103+
'mixins',
104+
'animations',
105+
'z-index',
106+
].map( ( imported ) => `@import "${ imported }";` ).join( ' ' ) +
107+
contents
108+
),
109+
} );
110+
111+
const result = await postcss( require( './post-css-config' ) ).process( builtSass.css, {
112+
from: 'src/app.css',
113+
to: 'dest/app.css',
114+
} );
115+
116+
const resultRTL = await postcss( [ require( 'rtlcss' )() ] ).process( result.css, {
117+
from: 'src/app.css',
118+
to: 'dest/app.css',
119+
} );
120+
121+
await Promise.all( [
122+
writeFile( outputFile, result.css ),
123+
writeFile( outputFileRTL, resultRTL.css ),
124+
] );
125+
},
126+
127+
async '.js'( file ) {
128+
for ( const [ environment, buildDir ] of Object.entries( JS_ENVIRONMENTS ) ) {
129+
const destPath = getBuildPath( file, buildDir );
130+
const babelOptions = getBabelConfig( environment, file.replace( PACKAGES_DIR, '@wordpress' ) );
131+
132+
const [ , transformed ] = await Promise.all( [
133+
makeDir( path.dirname( destPath ) ),
134+
babel.transformFileAsync( file, babelOptions ),
135+
] );
136+
137+
await Promise.all( [
138+
writeFile( destPath + '.map', JSON.stringify( transformed.map ) ),
139+
writeFile( destPath, transformed.code + '\n//# sourceMappingURL=' + path.basename( destPath ) + '.map' ),
140+
] );
141+
}
142+
},
143+
};
144+
145+
module.exports = async ( file, callback ) => {
146+
const extension = path.extname( file );
147+
const task = BUILD_TASK_BY_EXTENSION[ extension ];
148+
149+
if ( ! task ) {
150+
return;
151+
}
152+
153+
try {
154+
await task( file );
155+
callback();
156+
} catch ( error ) {
157+
callback( error );
158+
}
159+
};

0 commit comments

Comments
 (0)