Skip to content

Migrate webchannel-wrapper to gulp + google-closure-compiler #2891

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 19 commits into from
May 1, 2020
Merged
Show file tree
Hide file tree
Changes from 18 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: 0 additions & 4 deletions packages/webchannel-wrapper/.npmignore

This file was deleted.

19 changes: 19 additions & 0 deletions packages/webchannel-wrapper/externs/module.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* @license
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

/** @type {!Object} */
const module = {};
4 changes: 2 additions & 2 deletions packages/webchannel-wrapper/externs/overrides.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* @license
* Copyright 2017 Google Inc.
* Copyright 2017 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -30,7 +30,7 @@ goog.net.WebChannel.Options.messageHeaders;
/** @type {Object<string, string>|undefined} */
goog.net.WebChannel.Options.initMessageHeaders;

/** @type {stringboolean|undefined} */
/** @type {string|boolean|undefined} */
goog.net.WebChannel.Options.messageContentType;

/** @type {Object<string, string>|undefined|undefined} */
Expand Down
185 changes: 185 additions & 0 deletions packages/webchannel-wrapper/gulpfile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
/**
* @license
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

const gulp = require('gulp');
const rollup = require('rollup');
const closureCompiler = require('google-closure-compiler').gulp();
const del = require('del');
const path = require('path');
const sourcemaps = require('gulp-sourcemaps');
const { resolve } = require('path');
const commonjs = require('rollup-plugin-commonjs');
const rollupSourcemaps = require('rollup-plugin-sourcemaps');
const typescriptPlugin = require('rollup-plugin-typescript2');
const typescript = require('typescript');

// The optimization level for the JS compiler.
// Valid levels: WHITESPACE_ONLY, SIMPLE_OPTIMIZATIONS, ADVANCED_OPTIMIZATIONS.
const OPTIMIZATION_LEVEL = 'ADVANCED_OPTIMIZATIONS';

// For minified builds, wrap the output so we avoid leaking global variables.
const CJS_WRAPPER_PREFIX = `(function() {`;
const CJS_WRAPPER_SUFFIX =
`}).apply(typeof global !== 'undefined' ? ` +
`global : typeof self !== 'undefined' ? ` +
`self : typeof window !== 'undefined' ? window : {});`;

const closureLibRoot = path.dirname(
require.resolve('google-closure-library/package.json')
);

const closureDefines = [
// Avoid unsafe eval() calls (https://github.com/firebase/firebase-js-sdk/issues/798)
'goog.json.USE_NATIVE_JSON=true',
// Disable debug logging (saves 8780 bytes).
'goog.DEBUG=false',
// Disable fallbacks for running async code (saves 1472 bytes).
'goog.ASSUME_NATIVE_PROMISE=true',
// Disables IE8-specific event fallback code (saves 523 bytes).
'goog.events.CAPTURE_SIMULATION_MODE=0',
// Disable IE-Specific ActiveX fallback for XHRs (saves 524 bytes).
'goog.net.XmlHttpDefines.ASSUME_NATIVE_XHR=true'
];

/**
* Generates a closure compiler build of webchannel-wrapper.
* @param {string} filename name of the generated file
* @param {string} prefix prefix to the compiled code
* @param {string} suffix suffix to the compiled code
*/
function createBuildTask(filename, prefix, suffix) {
return function closureBuild() {
return gulp
.src(
[
`${closureLibRoot}/closure/goog/**/*.js`,
`${closureLibRoot}/third_party/closure/goog/**/*.js`,
'src/**/*.js'
],
{ base: '.' }
)
.pipe(sourcemaps.init())
.pipe(
closureCompiler({
js_output_file: filename,
output_wrapper: `${prefix}%output%${suffix}`,
entry_point: 'firebase.webchannel.wrapper',
compilation_level: OPTIMIZATION_LEVEL,
externs: [
resolve(__dirname, './externs/overrides.js'),
resolve(__dirname, './externs/module.js')
],
language_out: 'ECMASCRIPT_2017',
dependency_mode: 'PRUNE',
define: closureDefines
})
)
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest('dist'));
};
}

function createRollupTask({
inputPath,
outputExtension,
compileToES5 = false,
format = 'es'
}) {
return async function rollupBuild() {
const plugins = [rollupSourcemaps(), commonjs()];
if (compileToES5) {
plugins.push(
typescriptPlugin({
typescript,
// Uncomment for development only. Prevents caching between builds.
// clean: true,
Copy link
Member

Choose a reason for hiding this comment

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

Is it needed? I thought it is only necessary if we are doing custom source code transformation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is Typescript needed or is clean needed? Lack of clean seems to cause problems when trying different Typescript config options during development and it seems good to remind myself/others to use it next time we try to tweak the config.

Copy link
Member

Choose a reason for hiding this comment

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

clean. Should we always enable it then?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't think it's needed if you're not changing the Typescript config, and caching saves time.

Copy link
Member

@Feiyang1 Feiyang1 Apr 24, 2020

Choose a reason for hiding this comment

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

When should I enable it, I don't think we are changing the config? Sorry that I'm nitpicking. If it is not really needed, I think we should just remove it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I want to leave a note for anyone in the future who has to tinker with the build pipeline so they don't forget to enable this when working, or they will get really frustrated when changes to tsconfig don't seem to do anything. But I don't want to leave it on for production and regular usage. I don't know if a comment is the best place to leave that note, but if it's outside the code I don't think anyone will remember to check.

compilerOptions: { allowJs: true },
include: ['dist/**/*.js']
})
);
}
const inputOptions = {
input: inputPath,
plugins
};

const outputOptions = {
file: `dist/index${outputExtension ? '.' : ''}${outputExtension}.js`,
format,
sourcemap: true,
// Prevents warning when compiling CJS that there are named and default exports together.
exports: 'named'
};

const bundle = await rollup.rollup(inputOptions);
return bundle.write(outputOptions);
};
}

async function deleteIntermediateFiles() {
await del('dist/temp');
}

// Closure-generated ES2017 intermediate file (CJS format)
const intermediateCjsFile = 'temp/cjs.js';
const intermediateCjsPath = resolve(__dirname, 'dist/', intermediateCjsFile);
const cjsBuild = createBuildTask(
intermediateCjsFile,
CJS_WRAPPER_PREFIX,
CJS_WRAPPER_SUFFIX
);

// Closure-generated ES2017 intermediate file (no wrapper text)
const intermediateEsmFile = 'temp/esm.js';
const intermediateEsmPath = resolve(__dirname, 'dist/', intermediateEsmFile);
const esmBuild = createBuildTask(intermediateEsmFile, '', '');

// cjs output
const rollupCjsTask = createRollupTask({
inputPath: intermediateCjsPath,
outputExtension: '',
compileToES5: true,
format: 'cjs'
});
gulp.task('cjs', gulp.series(cjsBuild, rollupCjsTask));

// esm intermediateEsmPath
const rollupEsmTask = createRollupTask({
inputPath: intermediateEsmPath,
outputExtension: 'esm',
compileToES5: true,
format: 'es'
});
gulp.task('esm', gulp.series(esmBuild, rollupEsmTask));

// esm2017 output
const rollup2017Task = createRollupTask({
inputPath: intermediateEsmPath,
outputExtension: 'esm2017',
compileToES5: false,
format: 'es'
});
gulp.task('esm2017', gulp.series(esmBuild, rollup2017Task));

gulp.task(
'allEsm',
gulp.series(esmBuild, gulp.parallel(rollupEsmTask, rollup2017Task))
);

gulp.task('buildAll', gulp.parallel('cjs', 'allEsm'));

gulp.task('default', gulp.series('buildAll', deleteIntermediateFiles));
13 changes: 9 additions & 4 deletions packages/webchannel-wrapper/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,26 @@
"author": "Firebase <[email protected]> (https://firebase.google.com/)",
"main": "dist/index.js",
"module": "dist/index.esm.js",
"esm2017": "dist/index.esm2017.js",
"files": [
"dist"
],
"scripts": {
"dev": "watch 'yarn build' src",
"build": "node tools/build.js",
"build": "gulp",
"prepare": "yarn build"
},
"license": "Apache-2.0",
"devDependencies": {
"closure-builder": "2.3.8",
"google-closure-library": "20200224.0.0",
"google-closure-compiler": "20200406.0.0",
"google-closure-library": "20200406.0.0",
"gulp": "4.0.2",
"gulp-sourcemaps": "2.6.5",
"rollup": "2.6.1",
"rollup-plugin-commonjs": "10.1.0",
"rollup-plugin-sourcemaps": "0.5.0"
"rollup-plugin-sourcemaps": "0.5.0",
"rollup-plugin-typescript2": "0.27.0",
"typescript": "3.8.3"
},
"repository": {
"directory": "packages/webchannel-wrapper",
Expand Down
93 changes: 0 additions & 93 deletions packages/webchannel-wrapper/tools/build.js

This file was deleted.

8 changes: 8 additions & 0 deletions packages/webchannel-wrapper/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"extends": "../../config/tsconfig.base.json",
"compilerOptions": {
"declaration": false,
"outDir": "dist",
"downlevelIteration": true,
}
}
16 changes: 16 additions & 0 deletions test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* @license
* Copyright 2020 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
Loading