diff --git a/service-worker/worker/gulpfile.ts b/service-worker/worker/gulpfile.ts index b9e1cd8..9916300 100644 --- a/service-worker/worker/gulpfile.ts +++ b/service-worker/worker/gulpfile.ts @@ -14,6 +14,9 @@ var merge = require('merge-stream'); var exec = require('child_process').exec; var uglify = require('gulp-uglify'); var rename = require('gulp-rename'); +var webpack = require('webpack'); + +import AngularServiceWorkerPlugin from './src/webpack'; let assign = (dest, ...sources) => { sources.forEach(source => { @@ -44,13 +47,21 @@ gulp.task('clean', (done) => { rimraf('./dist', done); }); -gulp.task('prepublish', ['build']); +gulp.task('clean:src', done => { + rimraf('./dist/src', done); +}); + +gulp.task('prepublish', done => runSequence( + 'build', + 'clean:src', + done +)); gulp.task('build', done => runSequence( 'clean', [ 'task:companion:build', - 'task:generator:build', + 'task:webpack:build', 'task:worker:build' ], done @@ -71,6 +82,44 @@ gulp.task('generator:build', done => runSequence( 'task:generator:build', done)); +gulp.task('task:webpack_test:pack', done => { + console.log(process.cwd()); + webpack({ + context: `${process.cwd()}/src/test/webpack`, + entry: './index.js', + output: { + path: `${process.cwd()}/dist/src/test/webpack`, + filename: 'index.js' + }, + plugins: [ + new AngularServiceWorkerPlugin() + ] + }, () => done()) +}); + +gulp.task('task:webpack:build', done => runSequence( + 'task:webpack:compile', + 'task:webpack:copy_deploy', + done +)); + +gulp.task('task:webpack:compile', () => gulp + .src([ + 'src/webpack/**/*.ts' + ], { + base: 'src/webpack' + }) + .pipe(ts(commonCompilerConfig)) + .pipe(gulp.dest('dist'))); + +gulp.task('task:webpack:copy_deploy', () => gulp + .src([ + 'dist/src/webpack/index.js' + ], { + base: 'dist/src/webpack' + }) + .pipe(gulp.dest('dist/webpack'))); + gulp.task('task:companion:build', done => runSequence( 'task:companion:compile', 'task:companion:copy_deploy', diff --git a/service-worker/worker/package.json b/service-worker/worker/package.json index c8acb75..fbed25d 100644 --- a/service-worker/worker/package.json +++ b/service-worker/worker/package.json @@ -57,6 +57,7 @@ "base64-js": "^1.1.2", "broccoli-caching-writer": "^2.2.1", "fs-extra": "^0.30.0", - "jshashes": "^1.0.5" + "jshashes": "^1.0.5", + "webpack": "^2.1.0-beta.21" } } diff --git a/service-worker/worker/src/test/webpack/index.html b/service-worker/worker/src/test/webpack/index.html new file mode 100644 index 0000000..cc98798 --- /dev/null +++ b/service-worker/worker/src/test/webpack/index.html @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/service-worker/worker/src/test/webpack/index.js b/service-worker/worker/src/test/webpack/index.js new file mode 100644 index 0000000..5d62b27 --- /dev/null +++ b/service-worker/worker/src/test/webpack/index.js @@ -0,0 +1,4 @@ +// This is a test. +require('./other'); + +console.log('testing'); \ No newline at end of file diff --git a/service-worker/worker/src/test/webpack/other.js b/service-worker/worker/src/test/webpack/other.js new file mode 100644 index 0000000..3b4b519 --- /dev/null +++ b/service-worker/worker/src/test/webpack/other.js @@ -0,0 +1,2 @@ +// This is another file. +console.log('this is another file'); \ No newline at end of file diff --git a/service-worker/worker/src/webpack/index.ts b/service-worker/worker/src/webpack/index.ts new file mode 100644 index 0000000..6004318 --- /dev/null +++ b/service-worker/worker/src/webpack/index.ts @@ -0,0 +1,65 @@ +declare var require; + +let fs = require('fs'); +let SHA1 = require('jshashes').SHA1; + +/** + * Webpack plugin that generates a basic Angular service worker manifest. + */ +export default class AngularServiceWorkerPlugin { + + constructor(public manifestFile = 'ngsw-manifest.json') {} + + apply(compiler) { + // Determine the destination directory and the URL prefix for the app. + let outputPath = compiler.options.output.path; + let publicPrefix = compiler.options.output.publicPath || ''; + if (!outputPath) { + throw 'Must have output path set.'; + } + + // Used to compute version hashes. + let sha1 = new SHA1(); + + // Wait until webpack builds the whole output directory. Every file being + // deployed to the server needs to be included in the manifest. + compiler.plugin('done', stats => { + // Manifest into which assets to be fetched will be recorded. This will either + // be read from the existing template or created fresh. + let manifest: any = {}; + + // Look for an existing manifest. If there is one, parse it. + let manifestPath = `${outputPath}/${this.manifestFile}`; + if (fs.existsSync(manifestPath)) { + manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8')) || {}; + } + + // Validate that the manifest has a default group set up properly, with + // the map for its URLs. + if (!manifest.group) { + manifest.group = {}; + } + if (!manifest.group.default) { + manifest.group.default = {}; + } + if (!manifest.group.default.url) { + manifest.group.default.url = {}; + } + + // Go through every asset in the compilation and include it in the manifest, + // computing a hash for proper versioning. + Object + .keys(stats.compilation.assets) + .forEach(asset => { + let url = `${publicPrefix}/${asset}`; + manifest.group.default.url[url] = { + // TODO(alxhub): use webpack cached version if available. + hash: sha1.hex(fs.readFileSync(`${outputPath}/${asset}`, 'utf8')) + }; + }); + + // Write the merged manifest to disk. + fs.writeFileSync(manifestPath, JSON.stringify(manifest)); + }); + } +}