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

Convert bundling to use Rollup #213

Merged
merged 2 commits into from
Oct 18, 2021
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
4 changes: 1 addition & 3 deletions .babelrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,7 @@ module.exports = {
{
development: true,
runtime: 'automatic',
// Use `preact/compat/jsx-dev-runtime` which is an alias for `preact/jsx-runtime`.
// See https://github.com/preactjs/preact/issues/2974.
importSource: 'preact/compat',
importSource: 'preact',
},
],
],
Expand Down
9 changes: 8 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,12 @@
"react/react-in-jsx-scope": "off",
// Replaced by TypeScript's static checking.
"react/prop-types": "off"
}
},
"overrides": [
{
"files": ["rollup*.mjs", "scripts/pattern-library.js"],
"env": { "node": true },
"parserOptions": { "sourceType": "module" }
}
]
}
184 changes: 128 additions & 56 deletions gulpfile.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,22 @@
/* eslint-env node */
('use strict');
'use strict';

const fs = require('fs');
const path = require('path');

const commander = require('commander');
const log = require('fancy-log');
const glob = require('glob');
const gulp = require('gulp');
const rollup = require('rollup');
const sass = require('sass');

const createBundle = require('./scripts/gulp/create-bundle');
const createStyleBundle = require('./scripts/gulp/create-style-bundle');
const servePatternLibrary = require('./scripts/serve-pattern-library');

const IS_PRODUCTION_BUILD = process.env.NODE_ENV === 'production';

const SCRIPT_DIR = 'build/scripts';
const STYLE_DIR = 'build/styles';

const appBundles = [
{
// A web app to assist with testing UI components.
name: 'pattern-library',
entry: './scripts/pattern-library',
path: SCRIPT_DIR,
transforms: ['babel'],
},
];

const cssBundles = ['./styles/pattern-library.scss'];

function parseCommandLine() {
Expand Down Expand Up @@ -60,17 +50,57 @@ function parseCommandLine() {
}

const karmaOptions = parseCommandLine();
const { run } = require('./scripts/gulp/run');

function runKarma(done) {
const karma = require('karma');
new karma.Server(
{
configFile: `${__dirname}/src/karma.config.js`,
...karmaOptions,
},
done
).start();

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm making assumptions that this chunk of the diff is duplicative of the build functions in the client.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, indeed.

/** @param {import('rollup').RollupWarning} */
function logRollupWarning(warning) {
log.info(`Rollup warning: ${warning} (${warning.url})`);
}

async function buildJS(rollupConfig) {
let { default: configs } = await import(rollupConfig);
if (!Array.isArray(configs)) {
configs = [configs];
}

await Promise.all(
configs.map(async config => {
const bundle = await rollup.rollup({
...config,
onwarn: logRollupWarning,
});
await bundle.write(config.output);
})
);
}

async function watchJS(rollupConfig) {
const { default: configs } = await import(rollupConfig);
const watcher = rollup.watch(
configs.map(config => ({
...config,
onwarn: logRollupWarning,
}))
);

return new Promise(resolve => {
watcher.on('event', event => {
switch (event.code) {
case 'START':
log.info('JS build starting...');
break;
case 'BUNDLE_END':
event.result.close();
break;
case 'ERROR':
log.info('JS build error', event.error);
break;
case 'END':
log.info('JS build completed.');
resolve(); // Resolve once the initial build completes.
break;
}
});
});
}

/**
Expand All @@ -95,41 +125,13 @@ gulp.task('changelog', async () => {
console.log(changelog.toString());
});

/**
* Task to build a CSS bundle.
*
* nb. This is only used for unit tests that need CSS to verify accessibility requirements.
*/
gulp.task('build-test-css', done => {
fs.mkdirSync('build', { recursive: true });
const result = sass.renderSync({
file: 'styles/index.scss',
outFile: 'build/styles.css',
sourceMap: true,
});

fs.writeFileSync('build/styles.css', result.css);
fs.writeFileSync('build/styles.css.map', result.map);
done();
});

gulp.task(
'test',
gulp.series('build-test-css', done => runKarma(done))
);

gulp.task('serve-pattern-library', () => {
servePatternLibrary();
});

// The following tasks bundle assets for the pattern library for use locally
// during development. Bundled JS and CSS are not published with the package.

// Bundle JS into local `build` folder
gulp.task('bundle-js', () => {
return Promise.all(appBundles.map(config => createBundle(config)));
});

// Bundle SASS into local `build` folder
gulp.task('bundle-css', function () {
fs.mkdirSync(STYLE_DIR, { recursive: true });
Expand All @@ -150,11 +152,81 @@ gulp.task(
)
);

gulp.task('watch-js', () =>
Promise.all(appBundles.map(config => createBundle(config, { watch: true })))
);
gulp.task('watch-js', () => watchJS('./rollup.config.mjs'));

gulp.task(
'watch',
gulp.parallel('serve-pattern-library', 'watch-css', 'watch-js')
);

/**
* Task to build a CSS bundle.
*
* nb. This is only used for unit tests that need CSS to verify accessibility requirements.
*/
gulp.task('build-test-css', done => {
fs.mkdirSync('build', { recursive: true });
const result = sass.renderSync({
file: 'styles/index.scss',
outFile: 'build/styles.css',
sourceMap: true,
});

fs.writeFileSync('build/styles.css', result.css);
fs.writeFileSync('build/styles.css.map', result.map);
done();
});

async function buildAndRunTests() {
const { grep, singleRun } = karmaOptions;

// Generate an entry file for the test bundle. This imports all the test
// modules, filtered by the pattern specified by the `--grep` CLI option.
const testFiles = [
'test/bootstrap.js',
...glob
.sync('src/**/*-test.js')
.filter(path => (grep ? path.match(grep) : true)),
];

const testSource = testFiles
.map(path => `import "../../${path}";`)
.join('\n');

fs.mkdirSync('build/scripts', { recursive: true });
fs.writeFileSync('build/scripts/test-inputs.js', testSource);

// Build the test bundle.
log.info(`Building test bundle... (${testFiles.length} files)`);
if (singleRun) {
await buildJS('./rollup-tests.config.mjs');
} else {
await watchJS('./rollup-tests.config.mjs');
}

// Run the tests.
log.info('Starting Karma...');
return new Promise(resolve => {
const karma = require('karma');
new karma.Server(
karma.config.parseConfig(
path.resolve(__dirname, './src/karma.config.js'),
{ singleRun }
),
resolve
).start();

process.on('SIGINT', () => {
// Give Karma a chance to handle SIGINT and cleanup, but forcibly
// exit if it takes too long.
setTimeout(() => {
resolve();
process.exit(1);
}, 5000);
});
});
}

// Some (eg. a11y) tests rely on CSS bundles. We assume that JS will always take
// longer to build than CSS, so build in parallel.
gulp.task('test', gulp.parallel('build-test-css', buildAndRunTests));
31 changes: 8 additions & 23 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
"@babel/core": "^7.1.6",
"@babel/preset-env": "^7.1.6",
"@babel/preset-react": "^7.0.0",
"@rollup/plugin-babel": "^5.3.0",
"@rollup/plugin-commonjs": "^21.0.0",
"@rollup/plugin-node-resolve": "^13.0.5",
"@rollup/plugin-virtual": "^2.0.3",
"auto-changelog": "^2.2.1",
"autoprefixer": "^10.2.5",
"axe-core": "^4.0.0",
"babel-plugin-istanbul": "^6.0.0",
"babel-plugin-mockable-imports": "^1.7.1",
"babelify": "^10.0.0",
"browserify": "^17.0.0",
"chai": "^4.1.2",
"classnames": "^2.2.6",
"commander": "^7.1.0",
Expand All @@ -27,18 +29,17 @@
"eslint-plugin-mocha": "^8.0.0",
"eslint-plugin-react": "^7.12.4",
"eslint-plugin-react-hooks": "^4.0.4",
"exorcist": "^2.0.0",
"express": "^4.17.1",
"fancy-log": "^1.3.3",
"gulp": "^4.0.0",
"karma": "^6.0.1",
"karma-browserify": "^8.0.0",
"karma-chai": "^0.1.0",
"karma-chrome-launcher": "^3.1.0",
"karma-coverage-istanbul-reporter": "^3.0.3",
"karma-mocha": "^2.0.0",
"karma-mocha-reporter": "^2.0.4",
"karma-sinon": "^1.0.5",
"karma-source-map-support": "^1.4.0",
"mocha": "8.2.1",
"mustache": "^4.2.0",
"mustache-express": "^1.3.0",
Expand All @@ -47,12 +48,11 @@
"preact": "^10.4.0",
"prettier": "^2.2.1",
"puppeteer": "^7.1.0",
"rollup": "^2.58.0",
"rollup-plugin-string": "^3.0.0",
"sass": "^1.32.11",
"sinon": "^9.0.0",
"stringify": "^5.1.0",
"terser": "^5.7.0",
"typescript": "^4.1.5",
"watchify": "^4.0.0",
"yalc": "^1.0.0-pre.50"
},
"peerDependencies": {
Expand Down Expand Up @@ -82,20 +82,5 @@
],
"main": "./lib-cjs/index.js",
"module": "./lib/index.js",
"browserslist": "chrome 70, firefox 70, safari 11.1",
"browserify": {
"transform": [
[
"stringify",
{
"appliesTo": {
"includeExtensions": [
".html",
".svg"
]
}
}
]
]
}
"browserslist": "chrome 70, firefox 70, safari 11.1"
}
Loading