preact-cli icon indicating copy to clipboard operation
preact-cli copied to clipboard

Feature request: new build-time option removing inline scripts to develop browser extensions

Open kaznak opened this issue 3 years ago • 5 comments

Do you want to request a feature or report a bug?

request a feature

What is the current behaviour?

preact build generates index.html with inline scripts.

If the current behaviour is a bug, please provide the steps to reproduce.

not a bug

What is the expected behaviour?

preact build generates index.html without inline scripts. Current preact-cli generates inline scripts like below(unminified):

        <script type="__PREACT_CLI_DATA__">
            %7B%22preRenderData%22:%7B%22url%22:%22/%22%7D%7D
        </script>
        <script nomodule="">
            !(function() {
                var e = document,
                    t = e.createElement("script");
                if (!("noModule" in t) && "onbeforeload" in t) {
                    var n = !1;
                    e.addEventListener(
                        "beforeload",
                        function(e) {
                            if (e.target === t) n = !0;
                            else if (!e.target.hasAttribute("nomodule") || !n)
                                return;
                            e.preventDefault();
                        },
                        !0
                    ),
                        (t.type = "module"),
                        (t.src = "."),
                        e.head.appendChild(t),
                        t.remove();
                }
            })();
        </script>

I need to write out these scripts to files and load.

If this is a feature request, what is motivation or use case for changing the behaviour?

To develop browser extensions. Browsers forbid inline scripts without hash or nonce wrote in manifest.json as content security policy.

Please mention other relevant information.

The create-react-app supports this feature by environment variable switch, INLINE_RUNTIME_CHUNK.

Please paste the results of preact info here.


Environment Info:
  System:
    OS: macOS 10.15.7
    CPU: (8) x64 Intel(R) Core(TM) i5-8257U CPU @ 1.40GHz
  Binaries:
    Node: 14.15.1 - /var/folders/tf/2sbxxh5552nc03mb6kz7gvcr0000gn/T/yarn--1609001521817-0.4367070293127109/node
    Yarn: 1.22.10 - /var/folders/tf/2sbxxh5552nc03mb6kz7gvcr0000gn/T/yarn--1609001521817-0.4367070293127109/yarn
    npm: 6.14.8 - ~/.anyenv/envs/nodenv/versions/14.15.1/bin/npm
  Browsers:
    Chrome: 87.0.4280.88
    Firefox: 83.0
    Safari: 14.0.2
  npmPackages:
    preact: ^10.3.1 => 10.5.7 
    preact-cli: ^3.0.0 => 3.0.5 
    preact-render-to-string: ^5.1.4 => 5.1.12 
    preact-router: ^3.2.1 => 3.2.1 

✨  Done in 5.83s.

Thank you for reading!

kaznak avatar Dec 26 '20 17:12 kaznak

Sorry for the late response, you can just use a custom template to get this behavior I believe.

Copy the template if you do not already have one in your repo. Remove the <% preact.bodyEnd %> and then use the template via preact build --template path/to/template.html.

rschristian avatar Dec 31 '20 00:12 rschristian

@rschristian

No problem, thank you for answering. But removing <% preact.bodyEnd %> does not work.

It removes the code blocks I mentioned from the template.html and removes other critical code blocks, and then the app becomes blank completely.

Diff of The body element from with <% preact.bodyEnd %> to without it is as follows:

88,137c41
<     <body>
<         <div id="app">
<             <header class="header__3QGkI">
<                 <h1>Preact App</h1>
<                 <nav>
<                     <a href="/index.html" class="">Home</a
<                     ><a href="/profile" class="">Me</a
<                     ><a href="/profile/john" class="">John</a>
<                 </nav>
<             </header>
<             <div class="notfound__3HqSM">
<                 <h1>Error 404</h1>
<                 <p>That page doesn't exist.</p>
<                 <a href="/" class=""><h4>Back to Home</h4></a>
<             </div>
<         </div>
<         <script type="__PREACT_CLI_DATA__">
<             %7B%22preRenderData%22:%7B%22url%22:%22/%22%7D%7D
<         </script>
<         <script nomodule="">
<             !(function() {
<                 var e = document,
<                     t = e.createElement("script");
<                 if (!("noModule" in t) && "onbeforeload" in t) {
<                     var n = !1;
<                     e.addEventListener(
<                         "beforeload",
<                         function(e) {
<                             if (e.target === t) n = !0;
<                             else if (!e.target.hasAttribute("nomodule") || !n)
<                                 return;
<                             e.preventDefault();
<                         },
<                         !0
<                     ),
<                         (t.type = "module"),
<                         (t.src = "."),
<                         e.head.appendChild(t),
<                         t.remove();
<                 }
<             })();
<         </script>
<         <script
<             crossorigin="anonymous"
<             src="/bundle.58077.esm.js"
<             type="module"
<         ></script>
<         <script nomodule="" src="/polyfills.03bf6.js"></script>
<         <script nomodule="" defer="defer" src="/polyfills.03bf6.js"></script>
<     </body>
---
>     <body></body>

CSS code for the app is also removed even I kept the <% preact.headEnd %>.

The app div element and loading scripts, /bundle.58077.esm.js, /polyfills.03bf6.js and /polyfills.03bf6.js, is the application itself, but removed also.

Thank you for reading!

kaznak avatar Jan 01 '21 10:01 kaznak

CSS inlining should still be there, that's something unrelated.

There's some way to regex with the script src, though I forget exactly how.

Regardless, Preact-CLI is mainly for PWAs. You're mostly on your own if you want to cut out parts for an entirely different purpose. I don't think it really makes sense to add this functionality.

rschristian avatar Jan 01 '21 10:01 rschristian

I think adding support for non-inlined scripts could help harden PWAs as well via CSP. Here is the React equivalent: https://medium.com/@nrshahri/csp-cra-324dd83fe5ff

jmoore34 avatar Nov 06 '21 08:11 jmoore34

@jmoore34 That's the CRA equivalent, which is just Webpack. You can configure Preact-CLI's Webpack config as-is, see preact-cli#webpack.

That big Safari nomodule polyfill is gone now, and anything remaining you can strip out in a post-build yourself really. If there's something that you can't easily alter in the config or is preventing you from configuring as you'd like, certainly let me know.

rschristian avatar Nov 06 '21 09:11 rschristian

Closing this out, CLI's target is PWAs.

rschristian avatar Jan 05 '23 05:01 rschristian