Skip to content

Commit c58689b

Browse files
DavidParks8dherges
authored andcommitted
feat: minify UMD bundles (#205)
1 parent f27e8a0 commit c58689b

File tree

4 files changed

+97
-13
lines changed

4 files changed

+97
-13
lines changed

integration/samples/secondary/specs/assets.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,22 @@ describe(`@sample/secondary`, () => {
1919
});
2020
});
2121

22+
describe(`secondary-lib.umd.min.js`, () => {
23+
let GENERATED;
24+
before(done => {
25+
GENERATED = require(path.resolve(__dirname, '..', 'dist', 'bundles', 'secondary-lib.umd.min.js'));
26+
done();
27+
});
28+
29+
it(`should exist`, () => {
30+
expect(GENERATED).to.be.ok;
31+
});
32+
33+
it(`should have "BazComponent"`, () => {
34+
expect(GENERATED.BazComponent).to.be.ok;
35+
});
36+
});
37+
2238
describe(`secondary-lib-sub-module.umd.js`, () => {
2339
let GENERATED;
2440
before(done => {
@@ -35,4 +51,20 @@ describe(`@sample/secondary`, () => {
3551
});
3652
});
3753

54+
describe(`secondary-lib-sub-module.umd.min.js`, () => {
55+
let GENERATED;
56+
before(done => {
57+
GENERATED = require(path.resolve(__dirname, '..', 'dist', 'bundles', 'secondary-lib-sub-module.umd.min.js'));
58+
done();
59+
});
60+
61+
it(`should exist`, () => {
62+
expect(GENERATED).to.be.ok;
63+
});
64+
65+
it(`should have "BarComponent"`, () => {
66+
expect(GENERATED.BarComponent).to.be.ok;
67+
});
68+
});
69+
3870
});

src/lib/bundler.ts

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import { NgArtifactsFactory } from './model/ng-artifacts-factory';
44
import { writePackage } from './steps/package';
55
import { processAssets } from './steps/assets';
66
import { ngc } from './steps/ngc';
7-
import { remapSourcemap, relocateSourcemapRoot } from './steps/sorcery';
7+
import { minifyJsFile } from './steps/uglify';
8+
import { remapSourceMap, relocateSourceMapRoot } from './steps/sorcery';
89
import { rollup } from './steps/rollup';
910
import { downlevelWithTsc } from './steps/tsc';
1011
import { copySourceFilesToDestination } from './steps/transfer';
@@ -32,7 +33,7 @@ export async function generateNgBundle(ngPkg: NgPackageData): Promise<void> {
3233
// 2. NGC
3334
const es2015EntryFile: string = await ngc(ngPkg, baseBuildPath);
3435
// XX: see #46 - ngc only references to closure-annotated ES6 sources
35-
await remapSourcemap(`${baseBuildPath}/${ngPkg.flatModuleFileName}.js`);
36+
await remapSourceMap(`${baseBuildPath}/${ngPkg.flatModuleFileName}.js`);
3637

3738
// 3. FESM15: ROLLUP
3839
await rollup({
@@ -42,13 +43,13 @@ export async function generateNgBundle(ngPkg: NgPackageData): Promise<void> {
4243
dest: artifactPaths.es2015,
4344
externals: ngPkg.libExternals
4445
});
45-
await remapSourcemap(artifactPaths.es2015);
46+
await remapSourceMap(artifactPaths.es2015);
4647

4748
// 4. FESM5: TSC
4849
await downlevelWithTsc(
4950
artifactPaths.es2015,
5051
artifactPaths.module);
51-
await remapSourcemap(artifactPaths.module);
52+
await remapSourceMap(artifactPaths.module);
5253

5354
// 5. UMD: ROLLUP
5455
await rollup({
@@ -58,15 +59,19 @@ export async function generateNgBundle(ngPkg: NgPackageData): Promise<void> {
5859
dest: artifactPaths.main,
5960
externals: ngPkg.libExternals
6061
});
61-
await remapSourcemap(artifactPaths.main);
62+
await remapSourceMap(artifactPaths.main);
6263

63-
// 6. SOURCEMAPS: RELOCATE ROOT PATHS
64-
await relocateSourcemapRoot(ngPkg);
64+
// 6. UMD: Minify
65+
const minifiedFilePath: string = await minifyJsFile(artifactPaths.main);
66+
await remapSourceMap(minifiedFilePath);
6567

66-
// 7. COPY SOURCE FILES TO DESTINATION
68+
// 7. SOURCEMAPS: RELOCATE ROOT PATHS
69+
await relocateSourceMapRoot(ngPkg);
70+
71+
// 8. COPY SOURCE FILES TO DESTINATION
6772
await copySourceFilesToDestination(ngPkg, baseBuildPath);
6873

69-
// 8. WRITE PACKAGE.JSON and OTHER DOC FILES
74+
// 9. WRITE PACKAGE.JSON and OTHER DOC FILES
7075
const packageJsonArtifactPaths: NgArtifacts = artifactFactory.calculateArtifactPathsForPackageJson(ngPkg);
7176
await writePackage(ngPkg, packageJsonArtifactPaths);
7277

src/lib/steps/sorcery.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,19 @@ import { debug } from '../util/log';
99
*
1010
* @param sourceFile Source file
1111
*/
12-
export async function remapSourcemap(sourceFile: string): Promise<void> {
12+
export async function remapSourceMap(sourceFile: string): Promise<void> {
1313
debug(`re-mapping sources for ${sourceFile}`);
1414
const opts: any = {
1515
inline: false,
1616
includeContent: true,
1717
};
1818

19-
// Once sorcery loaded the chain of sourcemaps, the new sourcemap will be written asynchronously.
19+
// Once sorcery loads the chain of sourcemaps, the new sourcemap will be written asynchronously.
2020
const chain = await sorcery.load(sourceFile);
21+
if (!chain) {
22+
throw new Error('Failed to load sourceMap chain for ' + sourceFile);
23+
}
24+
2125
await chain.write(opts);
2226
}
2327

@@ -26,7 +30,7 @@ export async function remapSourcemap(sourceFile: string): Promise<void> {
2630
*
2731
* @param ngPkg Angular package data
2832
*/
29-
export async function relocateSourcemapRoot(ngPkg: NgPackageData): Promise<void> {
33+
export async function relocateSourceMapRoot(ngPkg: NgPackageData): Promise<void> {
3034
const replaceValue: string = `~/${ngPkg.fullPackageName}`;
3135
await modifyJsonFiles(`${ngPkg.buildDirectory}/**/*.js.map`, (sourceMap: any): any => {
3236
sourceMap.sources = sourceMap.sources

src/lib/steps/uglify.ts

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,44 @@
1-
const uglify = require('uglify-js');
1+
import { minify } from 'uglify-js';
2+
import { writeFile, readFile } from 'fs-extra';
3+
import { extname, basename } from 'path';
4+
import { debug, warn } from './../util/log';
5+
6+
export async function minifyJsFile(inputPath: string): Promise<string> {
7+
debug(`minifyJsFile: ${inputPath}`);
8+
9+
const fileExtension: string = extname(inputPath);
10+
const pathWithNoExtension: string = inputPath.substring(0, inputPath.length - fileExtension.length);
11+
12+
const outputPath: string = `${pathWithNoExtension}.min${fileExtension}`;
13+
const sourcemapOut: string = `${outputPath}.map`;
14+
const inputFileBuffer: Buffer = await readFile(inputPath);
15+
const inputSourceMapBuffer: Buffer = await readFile(`${inputPath}.map`);
16+
const result = minify(inputFileBuffer.toString(), {
17+
sourceMap: {
18+
content: inputSourceMapBuffer.toString(),
19+
url: basename(sourcemapOut)
20+
},
21+
parse: {
22+
bare_returns: true,
23+
},
24+
ie8: true,
25+
warnings: true,
26+
output: {
27+
comments: 'some'
28+
}
29+
});
30+
31+
if (result.warnings) {
32+
for(const warningMessage of result.warnings) {
33+
warn(warningMessage);
34+
}
35+
}
36+
37+
if (result.error) {
38+
throw result.error;
39+
}
40+
41+
await writeFile(outputPath, result.code);
42+
await writeFile(sourcemapOut, result.map);
43+
return outputPath;
44+
}

0 commit comments

Comments
 (0)