Skip to content

Replace Parcel with Rollup for manifest builder #389

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

Merged
merged 15 commits into from
Jul 8, 2020
6 changes: 6 additions & 0 deletions .changeset/from-parcel-to-rollup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@bigtest/bundler": minor
"@bigtest/server": minor
---

Refactor the manifest builder to use Rollup instead of Parcel.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
needs: prepack
strategy:
matrix:
package: [agent, cli, effection, logging, parcel, project, server, suite, todomvc, atom, webdriver]
package: [agent, cli, effection, logging, bundler, project, server, suite, todomvc, atom, webdriver]
steps:
- uses: actions/checkout@v1
- uses: actions/cache@v1
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"packages/agent",
"packages/driver",
"packages/webdriver",
"packages/parcel",
"packages/bundler",
"packages/project",
"packages/todomvc",
"packages/convergence",
Expand All @@ -42,6 +42,7 @@
},
"devDependencies": {
"@changesets/cli": "^2.8.0",
"@types/node": "^12",
"@frontside/eslint-config": "^1.1.0"
}
}
4 changes: 2 additions & 2 deletions packages/atom/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@
"ts-node": "*"
},
"dependencies": {
"effection": "0.7.0",
"@effection/events": "^0.7.4",
"@effection/subscription": "^0.7.2",
"@effection/subscription": "^0.9.0",
"effection": "0.7.0",
"ramda": "0.27.0"
},
"volta": {
Expand Down
File renamed without changes.
File renamed without changes.
33 changes: 33 additions & 0 deletions packages/bundler/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# @bigtest/bundler

Control Rollup with visibility into key work events.

Also, it isn't enough just to be running Rollup, we have to know that
it is up and running, and when new builds are available. For this, the
`Bundler` interface implements the `receive()` method to get messages about
when a new build is available.

## Synopsis

``` typescript
import { Bundler } from '@bigtest/bundler';
import { subscribe } from '@effection/subscription';

function* start() {
let bundler: Bundler = yield Bundler.create([{
entry: 'src/index.js',
outFile: 'dist/index.js'
}]);
let subscription = yield subscribe(bundler);

yield subscription.forEach(function*(message) {
console.log('new build happened:', message);
});
}
```

## Testing

``` shell
$ yarn test
```
24 changes: 16 additions & 8 deletions packages/parcel/package.json → packages/bundler/package.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"name": "@bigtest/parcel",
"version": "0.5.2",
"description": "Effection wrappers for working with parcel",
"main": "dist/src/index.js",
"typings": "dist/src/index.d.ts",
"name": "@bigtest/bundler",
"version": "0.5.1",
"description": "Effection wrappers for working with a bundler",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
"repository": "https://github.com/thefrontside/bigtest.git",
"author": "Frontside Engineering <[email protected]>",
"license": "MIT",
Expand All @@ -14,16 +14,24 @@
"scripts": {
"lint": "eslint 'src/**/*.ts' 'test/**/*.ts'",
"test": "mocha -r ts-node/register test/**/*.test.ts",
"start": "ts-node bin/start.ts",
"prepack": "tsc --outDir dist --declaration --sourcemap --module commonjs"
},
"dependencies": {
"@babel/core": "^7.10.4",
"@babel/plugin-transform-runtime": "^7.10.4",
"@babel/preset-env": "^7.10.4",
"@babel/preset-typescript": "^7.10.4",
"@babel/runtime": "^7.10.4",
"@bigtest/effection": "^0.5.1",
"@effection/channel": "^0.6.4",
"@effection/events": "^0.7.4",
"@effection/node": "^0.6.5",
"@rollup/plugin-babel": "^5.0.4",
"@rollup/plugin-commonjs": "^13.0.0",
"@rollup/plugin-node-resolve": "^8.1.0",
"effection": "^0.7.0",
"parcel": "^1.12.4",
"parcel-bundler": "^1.12.4"
"express": "^4.17.1",
"rollup": "^2.18.1"
},
"volta": {
"node": "12.16.0",
Expand Down
93 changes: 93 additions & 0 deletions packages/bundler/src/bundler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { Operation, resource } from 'effection';
import { on } from '@effection/events';
import { Subscribable, SymbolSubscribable } from '@effection/subscription';
import { Channel } from '@effection/channel';
import { watch, RollupWatchOptions, RollupWatcherEvent } from 'rollup';
import resolve from '@rollup/plugin-node-resolve';
import * as commonjs from '@rollup/plugin-commonjs';
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
import babel from '@rollup/plugin-babel';

interface BundleOptions {
entry: string;
outFile: string;
globalName?: string;
};

interface BundlerOptions {
mainFields: Array<"browser" | "main">;
};

export interface BundlerError extends Error {
frame: string;
};

export type BundlerMessage =
| { type: 'update' }
| { type: 'error'; error: BundlerError };

function prepareRollupOptions(bundles: Array<BundleOptions>, { mainFields }: BundlerOptions = { mainFields: ["browser", "main"] }): Array<RollupWatchOptions> {
return bundles.map(bundle => {
return {
input: bundle.entry,
output: {
file: bundle.outFile,
name: bundle.globalName || undefined,
sourcemap: true,
format: 'umd',
},
external: ['perf_hooks', '@babel/runtime'],
watch: {
exclude: ['node_modules/**']
},
plugins: [
resolve({
mainFields,
extensions: ['.js', '.ts']
}),
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
commonjs(),
babel({
babelHelpers: 'runtime',
extensions: ['.js', '.ts'],
presets: ['@babel/preset-env', '@babel/preset-typescript'],
plugins: ['@babel/plugin-transform-runtime']
})
]
}
});
}

export class Bundler implements Subscribable<BundlerMessage, undefined> {
private channel = new Channel<BundlerMessage>();

private get messages() {
return Subscribable.from(this.channel);
}

static *create(bundles: Array<BundleOptions>): Operation<Bundler> {
let bundler = new Bundler();
let rollup = watch(prepareRollupOptions(bundles));
let events = Subscribable
.from(on<Array<RollupWatcherEvent>>(rollup, 'event'))
.map(([event]) => event)
.filter(event => event.code === 'END' || event.code === 'ERROR')
.map(event => event.code === 'ERROR' ? { type: 'error', error: event.error } : { type: 'update' });

return yield resource(bundler, function*() {
try {
yield events.forEach(function*(message) {
bundler.channel.send(message as BundlerMessage);
});
} finally {
rollup.close();
}
});
}

[SymbolSubscribable]() {
return this.messages[SymbolSubscribable]();
}
}
1 change: 1 addition & 0 deletions packages/bundler/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { Bundler, BundlerMessage, BundlerError } from './bundler';
137 changes: 137 additions & 0 deletions packages/bundler/test/bundler.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import { describe } from 'mocha';
import { promises as fs, existsSync } from 'fs';
import * as expect from 'expect';
import * as rmrf from 'rimraf';
import { Subscribable } from '@effection/subscription';

import { spawn } from './world';
import { Bundler } from '../src/index';

describe("Bundler", function() {
this.timeout(5000);
let bundler: Bundler;

beforeEach((done) => rmrf('./build', done));
beforeEach(async () => {
await fs.mkdir("./build/test/sources", { recursive: true });
await fs.mkdir("./build/test/output", { recursive: true });
});

describe("JavaScript support", () => {
describe('success', () => {
beforeEach(async () => {
await fs.writeFile("./build/test/sources/input.js", "const foo = 'bar';\nexport default foo;\n");

bundler = await spawn(Bundler.create(
[{
entry: "./build/test/sources/input.js",
outFile: "./build/test/output/manifest.js",
globalName: "__bigtestManifest",
}],
));
await spawn(Subscribable.from(bundler).first());
});

it('builds the sources into the output directory', () => {
expect(existsSync("./build/test/output/manifest.js")).toEqual(true);
});

describe('introducing an error', () => {
beforeEach(async () => {
await fs.writeFile("./build/test/sources/input.js", "const foo - 'bar';\nexport default foo;\n");
});

it('emits an error event', async () => {
await expect(spawn(Subscribable.from(bundler).first())).resolves.toHaveProperty('type', 'error');
});
});
});

describe('failure', () => {
beforeEach(async () => {
await fs.writeFile("./build/test/sources/input.js", "const foo - 'bar';\nexport default foo;\n");

bundler = await spawn(Bundler.create(
[{
entry: "./build/test/sources/input.js",
outFile: "./build/test/output/manifest.js",
globalName: "__bigtestManifest",
}],
));
});

it('emits an error', async () => {
await expect(spawn(Subscribable.from(bundler).first())).resolves.toHaveProperty('type', 'error');
});

describe('fixing the error', () => {
beforeEach(async () => {
await spawn(Subscribable.from(bundler).first());
await fs.writeFile("./build/test/sources/input.js", "const foo = 'bar';\nexport default foo;\n");
});

it('emits an update event', async () => {
await expect(spawn(Subscribable.from(bundler).first())).resolves.toHaveProperty('type', 'update');
});
});
});
});

describe("TypeScript support", () => {
describe('success', () => {
beforeEach(async () => {
await fs.writeFile("./build/test/sources/input.ts", "const foo: string = 'bar';\nexport default foo;\n");

bundler = await spawn(Bundler.create(
[{
entry: "./build/test/sources/input.ts",
outFile: "./build/test/output/manifest.js",
globalName: "__bigtestManifest",
}],
));
await spawn(Subscribable.from(bundler).first());
});

it('builds the sources into the output directory', () => {
expect(existsSync("./build/test/output/manifest.js")).toEqual(true);
});
});

describe('type error', () => {
beforeEach(async () => {
await fs.writeFile("./build/test/sources/input.ts", "const foo: number = 'bar';\nexport default foo;\n");

bundler = await spawn(Bundler.create(
[{
entry: "./build/test/sources/input.ts",
outFile: "./build/test/output/manifest.js",
globalName: "__bigtestManifest",
}],
));
});

it('does not typecheck, just transform', async () => {
await expect(spawn(Subscribable.from(bundler).first())).resolves.toHaveProperty('type', 'update');
});
})
});

describe('editing the sources', () => {
beforeEach(async () => {
await fs.writeFile("./build/test/sources/input.ts", "const foo: string = 'bar';\nexport default foo;\n");

bundler = await spawn(Bundler.create(
[{
entry: "./build/test/sources/input.ts",
outFile: "./build/test/output/manifest.js",
globalName: "__bigtestManifest",
}],
));
await fs.writeFile("./build/test/sources/input.ts", "export default {hello: 'world'}\n");
});

it('notifies that a new build is available', async () => {
await expect(spawn(Subscribable.from(bundler).first())).resolves.toHaveProperty('type', 'update');
});
});
})
File renamed without changes.
4 changes: 4 additions & 0 deletions packages/bundler/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"extends": "@frontside/tsconfig",
"files": ["src/index.ts"]
}
4 changes: 2 additions & 2 deletions packages/effection/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@
"ts-node": "*"
},
"dependencies": {
"effection": "^0.7.0",
"@effection/events": "^0.7.4",
"@types/node": "^13.13.4"
"@types/node": "^13.13.4",
"effection": "^0.7.0"
},
"volta": {
"node": "12.16.0",
Expand Down
7 changes: 4 additions & 3 deletions packages/globals/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
"name": "@bigtest/globals",
"version": "0.6.0",
"description": "Global variable accesors for bigtest",
"main": "dist/index.js",
"typings": "dist/index.d.js",
"main": "dist/cjs/index.js",
"browser": "dist/esm/index.js",
"typings": "dist/types/index.d.js",
"repository": "https://github.com/thefrontside/bigtest.git",
"author": "Frontside Engineering <[email protected]>",
"license": "MIT",
Expand All @@ -15,7 +16,7 @@
"lint": "eslint '{src,test}/**/*.ts'",
"mocha": "mocha -r ts-node/register",
"test": "mocha -r ts-node/register test/**/*.test.ts",
"prepack": "tsc --outdir dist --declaration --sourcemap --module commonjs"
"prepack": "tsc --outdir dist/esm --sourcemap --module es2015 && tsc --outdir dist/cjs --sourcemap --module commonjs && tsc --outdir dist/types --emitDeclarationOnly"
},
"dependencies": {
"@bigtest/suite": "^0.5.2",
Expand Down
Loading