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

Build content script with :optimizations :none? #2

Closed
jacobmbr opened this Issue May 5, 2016 · 4 comments

Comments

Projects
None yet
2 participants
@jacobmbr

jacobmbr commented May 5, 2016

With the current setup, recompiling my content script takes ~10s, most of it spent applying the :whitespace optimization to over 100 sources.

On the other hand, passing :optimizations :none and a :main namespace to the compiler results in script tags with predictably wrong source paths being emitted.

Do you have a hint how to configure to build so I can develop without optimizations?
Thank you. Your work on this project is greatly appreciated.

@darwin

This comment has been minimized.

Show comment
Hide comment
@darwin

darwin May 5, 2016

Member

Unfortunately this is not easily possible. Content script has to be one javascript file because it is forbidden to load code dynamically into the content-script's javascript context (AFAIK).

I can see probably three options:

  1. build it with :optimizations :none mode and use some custom script to concatenate all generated scripts basically emulating :optimizations :whitespace but faster
  2. include all your 100+ scripts in unpacked manifest.json - this would be hard to maintain I guess
  3. implement some kind of "engine" in content script, which would inject-script tags into the page's own javascript content and boot your content-script app there (one person on Slack did that successfully)
Member

darwin commented May 5, 2016

Unfortunately this is not easily possible. Content script has to be one javascript file because it is forbidden to load code dynamically into the content-script's javascript context (AFAIK).

I can see probably three options:

  1. build it with :optimizations :none mode and use some custom script to concatenate all generated scripts basically emulating :optimizations :whitespace but faster
  2. include all your 100+ scripts in unpacked manifest.json - this would be hard to maintain I guess
  3. implement some kind of "engine" in content script, which would inject-script tags into the page's own javascript content and boot your content-script app there (one person on Slack did that successfully)
@darwin

This comment has been minimized.

Show comment
Hide comment
@darwin

darwin May 5, 2016

Member

I can also imagine a solution via a special Chrome extension using chrome debugger protocol to eval code inside content-script's javascript context on-demand.

We would patch goog.require in content-script's content to delegate script loading to this extension and it would do the work for it. This would be available only for development of course.

I'm not going to do that personally, because I didn't hit the annoyance level as you did. My content scripts are pretty small and my beefy iMac can deal with them pretty well :-)

Member

darwin commented May 5, 2016

I can also imagine a solution via a special Chrome extension using chrome debugger protocol to eval code inside content-script's javascript context on-demand.

We would patch goog.require in content-script's content to delegate script loading to this extension and it would do the work for it. This would be available only for development of course.

I'm not going to do that personally, because I didn't hit the annoyance level as you did. My content scripts are pretty small and my beefy iMac can deal with them pretty well :-)

@jacobmbr

This comment has been minimized.

Show comment
Hide comment
@jacobmbr

jacobmbr May 5, 2016

Thanks for getting back so quickly. I figured out a way using the ClosureBuilder Python script included in Google Closure, maybe this can save another stranded soul some hours:

  • Compile with :optimizations :none.
  • Use the :notify-command hook to call a shell script executing closurebuilder.py with --namespace="chromex_sample.content_script" --root="resources/unpacked/compiled/content_script and -o script. This builds a dependency tree from source and emits one big concatenated script with dependencies in the correct order.
  • Pipe output to a file, overwriting the initial output from the lein content task.
  • Include a new file override.js in the unpacked manifest.json that sets two variables:
var CLOSURE_NO_DEPS = true;
var CLOSURE_UNCOMPILED_DEFINES = null;

See here for another solution using eval injection as you alluded to. Not suitable for me b/c I need to stay in the isolated world to access Chrome APIs (and it feels slightly wrong).


CLJS-851 suggests that this general problem is known to the CLJS devs, but the fix just writes more script tags into a html page that doesn't exist in this case. shadow-build is mentioned as a solution, but I didn't get it to work.

jacobmbr commented May 5, 2016

Thanks for getting back so quickly. I figured out a way using the ClosureBuilder Python script included in Google Closure, maybe this can save another stranded soul some hours:

  • Compile with :optimizations :none.
  • Use the :notify-command hook to call a shell script executing closurebuilder.py with --namespace="chromex_sample.content_script" --root="resources/unpacked/compiled/content_script and -o script. This builds a dependency tree from source and emits one big concatenated script with dependencies in the correct order.
  • Pipe output to a file, overwriting the initial output from the lein content task.
  • Include a new file override.js in the unpacked manifest.json that sets two variables:
var CLOSURE_NO_DEPS = true;
var CLOSURE_UNCOMPILED_DEFINES = null;

See here for another solution using eval injection as you alluded to. Not suitable for me b/c I need to stay in the isolated world to access Chrome APIs (and it feels slightly wrong).


CLJS-851 suggests that this general problem is known to the CLJS devs, but the fix just writes more script tags into a html page that doesn't exist in this case. shadow-build is mentioned as a solution, but I didn't get it to work.

@darwin

This comment has been minimized.

Show comment
Hide comment
@darwin

darwin May 6, 2016

Member

I'm glad you found a solution. Yeah the linked blogpost about eval injection was done by the person from Slack channel.

I did read some more docs on Content Scripts CSP and they claim eval is not forbidden in Content Scripts. Maybe it would be just matter of patching goog to use some alternative method of fetching the sources and eval'ing them in the context of Content Script.

I did something similar once in the Atom (Electron) package:
https://github.com/darwin/plastic/blob/master/lib/worker.js

Member

darwin commented May 6, 2016

I'm glad you found a solution. Yeah the linked blogpost about eval injection was done by the person from Slack channel.

I did read some more docs on Content Scripts CSP and they claim eval is not forbidden in Content Scripts. Maybe it would be just matter of patching goog to use some alternative method of fetching the sources and eval'ing them in the context of Content Script.

I did something similar once in the Atom (Electron) package:
https://github.com/darwin/plastic/blob/master/lib/worker.js

darwin added a commit that referenced this issue Jun 28, 2017

@darwin darwin closed this Nov 9, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment