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

Add watch support for stylesheets in packages #8380

Merged
merged 3 commits into from
Aug 3, 2018
Merged
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
67 changes: 53 additions & 14 deletions bin/packages/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@ function getPackageName( file ) {
return path.relative( PACKAGES_DIR, file ).split( path.sep )[ 0 ];
}

const isJsFile = ( filepath ) => {
return /.\.js$/.test( filepath );
};

const isScssFile = ( filepath ) => {
return /.\.scss$/.test( filepath );
};

/**
* Get Build Path for a specified file
*
Expand All @@ -62,18 +70,51 @@ function getBuildPath( file, buildFolder ) {
}

/**
* Build a file for the required environments (node and ES5)
* Given a list of scss and js filepaths, divide them into sets them and rebuild.
*
* @param {Array} files list of files to rebuild
*/
function buildFiles( files ) {
// Reduce files into a unique sets of javaScript files and scss packages.
const buildPaths = files.reduce( ( accumulator, filePath ) => {
if ( isJsFile( filePath ) ) {
accumulator.jsFiles.add( filePath );
} else if ( isScssFile( filePath ) ) {
const pkgName = getPackageName( filePath );
const pkgPath = path.resolve( PACKAGES_DIR, pkgName );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In another PR #8287 I have the use-case for multiple SASS entry points (multiple CSS outputs) per package. Do you have some ideas on how this would play together?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The simplest way I can think of is to add some kind of config, potentially as a custom property to the package.json that could be picked up by the build scripts:

{
  scssEntryPoints: [
    'style.scss',
    'some/other/style.scss'
  ],
}

Either that or some kind of naming convention e.g. styles.main.scss.

I think the config idea is safer.

accumulator.scssPackagePaths.add( pkgPath );
}
return accumulator;
}, { jsFiles: new Set(), scssPackagePaths: new Set() } );

buildPaths.jsFiles.forEach( buildJsFile );
buildPaths.scssPackagePaths.forEach( buildPackageScss );
}

/**
* Build a javaScript 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' );
function buildJsFile( file, silent ) {
buildJsFileFor( file, silent, 'main' );
buildJsFileFor( file, silent, 'module' );
}

function buildStyle( packagePath ) {
/**
* Build a package's scss styles
*
* @param {string} packagePath The path to the package.
*/
function buildPackageScss( packagePath ) {
const styleFile = path.resolve( packagePath, SRC_DIR, 'style.scss' );

// Return early if the package has no root style file.
if ( ! fs.existsSync( styleFile ) ) {
return;
}

const outputFile = path.resolve( packagePath, BUILD_DIR.style, 'style.css' );
const outputFileRTL = path.resolve( packagePath, BUILD_DIR.style, 'style-rtl.css' );
mkdirp.sync( path.dirname( outputFile ) );
Expand Down Expand Up @@ -119,7 +160,7 @@ function buildStyle( packagePath ) {
* @param {boolean} silent Show logs
* @param {string} environment Dist environment (node or es5)
*/
function buildFileFor( file, silent, environment ) {
function buildJsFileFor( file, silent, environment ) {
const buildDir = BUILD_DIR[ environment ];
const destPath = getBuildPath( file, buildDir );
const babelOptions = getBabelConfig( environment );
Expand All @@ -145,7 +186,7 @@ function buildFileFor( file, silent, environment ) {
*/
function buildPackage( packagePath ) {
const srcDir = path.resolve( packagePath, SRC_DIR );
const files = glob.sync( `${ srcDir }/**/*.js`, {
const jsFiles = glob.sync( `${ srcDir }/**/*.js`, {
ignore: [
`${ srcDir }/**/test/**/*.js`,
`${ srcDir }/**/__mocks__/**/*.js`,
Expand All @@ -155,21 +196,19 @@ function buildPackage( packagePath ) {

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

files.forEach( ( file ) => buildFile( file, true ) );
// Build js files individually.
jsFiles.forEach( ( file ) => buildJsFile( file, true ) );

// Building styles
const styleFile = path.resolve( srcDir, 'style.scss' );
if ( fs.existsSync( styleFile ) ) {
buildStyle( packagePath );
}
// Build entire package scss.
buildPackageScss( packagePath );

process.stdout.write( `${ DONE }\n` );
}

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

if ( files.length ) {
files.forEach( buildFile );
buildFiles( files );
} else {
process.stdout.write( chalk.inverse( '>> Building packages \n' ) );
getPackages()
Expand Down
2 changes: 1 addition & 1 deletion bin/packages/watch.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const exists = ( filename ) => {

// Exclude deceitful source-like files, such as editor swap files.
const isSourceFile = ( filename ) => {
return /.\.js$/.test( filename );
return /.\.(js|scss)$/.test( filename );
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if we'd need some kind of rule excluding the components package scss from being watched, since that will end up being watched by both webpack and this script.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's fine :) it will generate a new CSS for the package but not use it in the webpack build.

};

const rebuild = ( filename ) => filesToBuild.set( filename, true );
Expand Down