Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: phase-2 p.o.c: break the app into packages #81

Draft
wants to merge 10 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ artifacts

# build/release artifacts
build/
build-module/
build-style/
wpgraphql-ide/
wpgraphql-ide.zip
/test-results/
Expand Down
8 changes: 8 additions & 0 deletions babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module.exports = ( api ) => {
api.cache( true );

return {
presets: [ '@wordpress/babel-preset-default' ],
plugins: [ '@emotion/babel-plugin', 'babel-plugin-inline-json-import' ],
};
};
211 changes: 211 additions & 0 deletions bin/packages/build-worker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
/**
* External dependencies
*
* This file includes code originally written by Automattic and contributors of the
* WordPress/gutenberg plugin, and is released under the terms of the GNU General Public License
* version 2.0 (GPLv2).
*
* @see https://github.com/WordPress/gutenberg
*/
const { promisify } = require( 'util' );
const fs = require( 'fs' );
const path = require( 'path' );
const babel = require( '@babel/core' );
const makeDir = require( 'make-dir' );
const sass = require( 'sass' );
const postcss = require( 'postcss' );
/**
* Internal dependencies
*/
const getBabelConfig = require( './get-babel-config' );

/**
* Path to packages directory.
*
* @type {string}
*/
const PACKAGES_DIR = path
.resolve( __dirname, '../../packages' )
.replace( /\\/g, '/' );

/**
* Mapping of JavaScript environments to corresponding build output.
*
* @type {Object}
*/
const JS_ENVIRONMENTS = {
main: 'build',
module: 'build-module',
};

/**
* Promisified fs.readFile.
*
* @type {Function}
*/
const readFile = promisify( fs.readFile );

/**
* Promisified fs.writeFile.
*
* @type {Function}
*/
const writeFile = promisify( fs.writeFile );

/**
* Promisified sass.render.
*
* @type {Function}
*/
const renderSass = promisify( sass.render );

/**
* 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' );
const pkgBuildPath = path.resolve( PACKAGES_DIR, pkgName, buildFolder );
const relativeToSrcPath = path.relative( pkgSrcPath, file );
return path.resolve( pkgBuildPath, relativeToSrcPath );
}

async function buildCSS( file ) {
const outputFile = getBuildPath(
file.replace( '.scss', '.css' ),
'build-style'
);
const outputFileRTL = getBuildPath(
file.replace( '.scss', '-rtl.css' ),
'build-style'
);

const [ , contents ] = await Promise.all( [
makeDir( path.dirname( outputFile ) ),
readFile( file, 'utf8' ),
] );

// const importLists = [
// 'colors',
// 'breakpoints',
// 'variables',
// 'mixins',
// 'animations',
// 'z-index',
// ]
// // Editor and component styles should be excluded from the default CSS vars output.
// .concat(
// file.includes( 'common.scss' ) ||
// ! (
// file.includes( 'block-library' ) ||
// file.includes( 'components' )
// )
// ? [ 'default-custom-properties' ]
// : []
// )
// .map( ( imported ) => `@import "${ imported }";` )
// .join( ' ' );
//
const builtSass = await renderSass( {
file,
includePaths: [ path.join( PACKAGES_DIR, 'base-styles' ) ],
data: ''.concat( '@use "sass:math";', contents ),
} );

const result = await postcss(
require( '@wordpress/postcss-plugins-preset' )
).process( builtSass.css, {
from: 'src/app.css',
to: 'dest/app.css',
} );

const resultRTL = await postcss( [ require( 'rtlcss' )() ] ).process(
result.css,
{
from: 'src/app.css',
to: 'dest/app.css',
}
);

await Promise.all( [
writeFile( outputFile, result.css ),
writeFile( outputFileRTL, resultRTL.css ),
] );
}

async function buildJS( file ) {
for ( const [ environment, buildDir ] of Object.entries(
JS_ENVIRONMENTS
) ) {
const destPath = getBuildPath(
file.replace( /\.(tsx|jsx)?$/, '.js' ),
buildDir
);
const babelOptions = getBabelConfig(
environment,
file.replace( PACKAGES_DIR, '@wordpress' )
);

const [ , transformed ] = await Promise.all( [
makeDir( path.dirname( destPath ) ),
babel.transformFileAsync( file, babelOptions ),
] );

await Promise.all( [
writeFile( destPath + '.map', JSON.stringify( transformed.map ) ),
writeFile(
destPath,
transformed.code +
'\n//# sourceMappingURL=' +
path.basename( destPath ) +
'.map'
),
] );
}
}

/**
* Object of build tasks per file extension.
*
* @type {Object<string,Function>}
*/
const BUILD_TASK_BY_EXTENSION = {
'.scss': buildCSS,
'.css': buildCSS,
'.js': buildJS,
'.jsx': buildJS,
'.ts': buildJS,
'.tsx': buildJS,
};

module.exports = async ( file, callback ) => {
const extension = path.extname( file );
const task = BUILD_TASK_BY_EXTENSION[ extension ];

if ( ! task ) {
callback( new Error( `No handler for extension: ${ extension }` ) );
}

try {
await task( file );
callback();
} catch ( error ) {
callback( error );
}
};
Loading
Loading