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

Adds brotli support for modern javascript #674

Merged
merged 36 commits into from
Apr 5, 2019
Merged

Adds brotli support for modern javascript #674

merged 36 commits into from
Apr 5, 2019

Conversation

prateekbh
Copy link
Member

@prateekbh prateekbh commented Nov 27, 2018

What kind of change does this PR introduce?

Feature

Did you add tests for your changes?
WIP

Summary
This PR does the following

  • Adds brotli support for precaching first party modern javascript, hence reducing the total cost/ total download amount from network to the end user.

  • Puts this behind a flag as one needs to add headers to their jS serving infra, before enabling this(see the added console.log)

  • Switches the underlying sw builder from sw-precache to workbox, for better extendable code.(next PR png -> webP)

  • Adds the capability to copy sw.js into user land and add custom logic to it.

  • Fixes [next] Service Worker precaches HTML files, but they aren't used #751

We only add brotli support modern js because we can be sure without a test that browser supporting esm supports brotli.

Does this PR introduce a breaking change?
Yes, the existing preact-cli-sw-precache plugins wont work anymore.

But the users will be able to just copy our sw.js file into their src root and add custom logic to it.

@prateekbh
Copy link
Member Author

Note: We can extend this support to css files as well

@prateekbh prateekbh changed the title WIP: Adds brotli support for modern javascript Adds brotli support for modern javascript Dec 5, 2018
Copy link
Member

@developit developit left a comment

Choose a reason for hiding this comment

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

Couple of things, some important some not.

// Before saving the response in cache, we need to treat the headers.
async cacheWillUpdate({request, response}) {
if (/.js.br$/.test(request.url)) {
const headers = response.headers;
Copy link
Member

Choose a reason for hiding this comment

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

Would this work instead of manually cloning?

response = response.clone();
response.headers.set('content-type', 'application/javascript')
return response;

Copy link
Member

Choose a reason for hiding this comment

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

This should – it's what my service workers are doing, tho I just pray that they work

Copy link
Member Author

Choose a reason for hiding this comment

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

am i doing something wrong here?

screen shot 2018-12-07 at 3 51 38 pm

Copy link
Member

@developit developit Feb 13, 2019

Choose a reason for hiding this comment

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

my bad - this would work though:

const headers = new Headers(clonedResponse.headers);
newHeaders.set('content-type', 'application/javascript');
return new Response(await clonedResponse.text(), { headers })

Copy link
Member Author

Choose a reason for hiding this comment

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

fixed

packages/cli/lib/lib/sw.js Show resolved Hide resolved
}),
);
}
if (config['sw']) {
Copy link
Member

Choose a reason for hiding this comment

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

Any reason this isn't config.sw?

Copy link
Member Author

Choose a reason for hiding this comment

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

nups, fixed

sw: swSrc,
},
target: 'webworker',
output: {
Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

done.. i guess?

filename: '[name]-esm.js',
beforeStartExecution: (plugins) => {
plugins.forEach(plugin => {
if (plugin.constructor.name === 'DefinePlugin' && plugin.definitions) {
Copy link
Member

Choose a reason for hiding this comment

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

What's the reason for only mutating values in-place here - does this fix DefinePlugin definitions leaking into the parent compiler?

Otherwise this could just be

plugins.forEach(plugin => {
  if (plugin.constructor.name === 'DefinePlugin') {
    if (!plugin.definitions) throw Error('ESM Error:  DefinePlugin found without definitions.');
    plugin.definitions['process.env.ES_BUILD'] = 'true';
  }
});

Copy link
Member Author

Choose a reason for hiding this comment

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

good point, i can chk that

Copy link
Member Author

Choose a reason for hiding this comment

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

works, fixed


let swSrc = resolve(__dirname, './../sw.js');
if (fs.existsSync(resolve(`${src}/sw.js`))) {
console.log(yellow('⚛️ Info - CLI found sw.js in source root folder, using that to compile the final service worker instead'));
Copy link
Member

Choose a reason for hiding this comment

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

Nit: can we make this a different color like blue? yellow seems like a warning, this is informational.

Also maybe shorten the message since it's a heads-up that will be shown every build? Or only show the message when things change (first build or sw.js added/removed):

  // only warn on first build, OR on rebuild if sw.js is added/removed:
  let swSrc = resolve(__dirname, './../sw.js');
  const exists = fs.existsSync(resolve(`${src}/sw.js`));
  if (exists !== global.hasSeenSw) {
    global.hasSeenSw = exists;
    if (exists) {
      console.log(blue('⚛️ Detected custom sw.js: compiling instead of default Service Worker.'));
    }
    else {
      console.log(blue('⚛️ No custom sw.js detected: compiling default Service Worker.'));
    }
  }

Copy link
Member Author

Choose a reason for hiding this comment

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

done

);
};
)];
if (env.sw) {
Copy link
Member

Choose a reason for hiding this comment

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

Is the Array return here done with the intention of moving to a MultiCompiler? This seems like it'll break in future Workbox versions that use child compilation.

Copy link
Member Author

Choose a reason for hiding this comment

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

How is the child compiler affected by the its parent compilation mode?

@prateekbh
Copy link
Member Author

@developit I re-did this with a child compiler, please review

ForsakenHarmony and others added 3 commits January 26, 2019 01:45
# Conflicts:
#	packages/cli/lib/lib/entry.js
#	packages/cli/lib/lib/webpack/webpack-client-config.js
#	packages/cli/package.json
sw: swSrc,
};
childCompiler.options.target = 'webworker';
childCompiler.options.output = JSON.parse(
Copy link
Member Author

@prateekbh prateekbh Mar 7, 2019

Choose a reason for hiding this comment

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

@developit @ForsakenHarmony do we have any dep already which can help me do this deepcopy?

Copy link
Member Author

Choose a reason for hiding this comment

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

nvm fixed it

@ForsakenHarmony ForsakenHarmony changed the base branch from next to master March 19, 2019 19:01
@@ -22,6 +23,15 @@ module.exports = async function(src, argv) {
);
}

if (argv.brotli) {
console.log(
Copy link
Member

Choose a reason for hiding this comment

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

guess this should use the util log fn

)
);
} else {
console.log(
Copy link
Member

Choose a reason for hiding this comment

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

same thing here?

Copy link
Member

@ForsakenHarmony ForsakenHarmony left a comment

Choose a reason for hiding this comment

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

Other than that looks good

Copy link
Member

@developit developit left a comment

Choose a reason for hiding this comment

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

its alive!

@prateekbh
Copy link
Member Author

  • Will fix these
  • Merge this
  • Release RC
  • Write tests

@prateekbh
Copy link
Member Author

Fixed comments!

@prateekbh prateekbh merged commit efdb448 into master Apr 5, 2019
@prateekbh prateekbh deleted the sw-webpack branch April 5, 2019 07:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants