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

[Violation] Avoid using document.write() #1600

Closed
2 of 10 tasks
bramjoosten opened this issue Sep 4, 2018 · 11 comments
Closed
2 of 10 tasks

[Violation] Avoid using document.write() #1600

bramjoosten opened this issue Sep 4, 2018 · 11 comments
Assignees

Comments

@bramjoosten
Copy link

bramjoosten commented Sep 4, 2018

Issue details

Chrome nags about using document.write(), it's a bad practice and may break in the future.

Steps to reproduce/test case

  1. open chrome devtools
  2. set error reporting to verbose.

Please specify which version of Browsersync, node and npm you're running

  • Browsersync [2.24.7]
  • Node [8.9.4]
  • Npm [5.6.0]

Affected platforms

  • linux
  • windows
  • OS X
  • freebsd
  • solaris
  • other (please specify which)

Browsersync use-case

  • API
  • Gulp
  • Grunt
  • CLI

for all other use-cases, (gulp, grunt etc), please show us exactly how you're using Browsersync

const browserSync = BrowserSync.create();

@WillsB3
Copy link

WillsB3 commented Jan 7, 2019

This also affects using BrowserSync on sites which use a Content Security Policy. See Refactor calls to JS APIs incompatible with CSP in this documentation.

@machito
Copy link

machito commented Oct 8, 2019

+1

@haydenbr
Copy link

For what it's worth, I took a shot at fixing this, but I ran into trouble actually building browser-sync locally.

using node v8.15.0, npm v6.4.1

Version: webpack 3.12.0
Time: 942ms
        Asset     Size  Chunks                    Chunk Names
    js/app.js  1.44 MB       0  [emitted]  [big]  main
js/app.js.map  1.75 MB       0  [emitted]         main
   [4] ./module.js 82 bytes {0} [built]
  [25] multi ./app.js 28 bytes {0} [built]
  [26] ./app.js 1.16 kB {0} [built]
  [35] ./modules/bsDisconnect.js 1.89 kB {0} [built]
  [36] ./modules/bsNotify.js 2 kB {0} [built]
  [37] ./modules/bsHistory.js 1.29 kB {0} [built]
  [38] ./modules/bsClients.js 1.05 kB {0} [built]
  [39] ./modules/bsSocket.js 2.4 kB {0} [built]
  [67] ./services/Pages.js 1.44 kB {0} [built]
  [68] ./services/Options.js 296 bytes {0} [built]
  [69] ./modules/bsStore.js 1.34 kB {0} [built]
  [72] ./main/controller.js 3.34 kB {0} [built]
  [73] ./filters.js 413 bytes {0} [built]
  [75] ./directives.js 293 bytes {0} [built]
  [77] ./directives/link-to.js 656 bytes {0} [built]
    + 65 hidden modules

ERROR in js/app.js from UglifyJs
Unexpected token: name (index) [js/app.js:224,5]
+ Results from 'build-all'
└─┬ build-all
  └─┬ build-js
    └─┬ webpack
      └── x @npm webpack (1.47s)
          Previous command failed with exit code 2

@haydenbr
Copy link

And I'm thinking this is the change that should be made to fix the original issue.

Replace the contents of script-tags.tmpl with this:

<script id="__bs_script__">//<![CDATA[
    let bsScript = document.createElement('script');
    bsScript.setAttribute('async', '');
    setAttribute('src', '%script%'.replace("HOST", location.hostname))
//]]></script>

@maxzz
Copy link

maxzz commented Dec 10, 2019

And I'm thinking this is the change that should be made to fix the original issue.

Replace the contents of script-tags.tmpl with this:

<script id="__bs_script__">//<![CDATA[
    let bsScript = document.createElement('script');
    bsScript.setAttribute('async', '');
    setAttribute('src', '%script%'.replace("HOST", location.hostname))
//]]></script>

A slightly corrected version will remove annoying message in DevTools:

<script id="__bs_script__">//<![CDATA[
    let script = document.createElement('script');
    script.setAttribute('async', '');
    script.setAttribute('src', '%script%'.replace("HOST", location.hostname));
    document.body.appendChild(script);
//]]></script>

@haydenbr
Copy link

@maxzz Oh yeah. That makes more sense. Looking back at what I wrote, I don't think I completed the thought.

Were you able to get browser-sync to build locally?

JohnGemstone added a commit to JohnGemstone/browser-sync that referenced this issue Jan 16, 2020
As per issue BrowserSync#1600 Chrome browsers throw a violation warning in the console when `document.write` is used for injecting elements.
Using the 'appendChild' method to inject the script tag mitigates the violation.

Violation reference:
https://developers.google.com/web/updates/2016/08/removing-document-write
@glen-84
Copy link
Contributor

glen-84 commented May 28, 2021

// TODO: Workaround for https://github.com/BrowserSync/browser-sync/issues/1600.
snippetOptions: {
    rule: {
        match: /<\/head>/u,
        fn(snippet, match) {
            const {
                groups: {src}
            } = /src='(?<src>[^']+)'/u.exec(snippet);

            return `<script src="${src}" async></script>${match}`;
        }
    }
}

@cmolina
Copy link

cmolina commented Jan 16, 2022

I faced a similar problem while trying to implement a Content Security Policy: I needed an inline script that doesn't use document.write(), so I mixed the ideas from @glen-84 and @haydenbr / @maxzz.

eleventyConfig.setBrowserSyncConfig({
  snippetOptions: {
    rule: {
      match: /<\/body>/i,
      fn(snippet, match) {
        const { src } = /src='(?<src>[^']+)'/u.exec(snippet).groups;

        return `<script>${generateScript(src)}</script>${match}`;
      },
    }
  },
});

function generateScript(src) {
  return `
  let script = document.createElement('script');
  script.setAttribute('async', '');
  script.setAttribute('src', '${src}');
  document.body.appendChild(script);`;
}

@mvaleno
Copy link

mvaleno commented Apr 14, 2022

This really is not fixed yet. From 2018, is it that hard to fix? Probably not happening, huh?

I'm a JavaScript beginner, and I can't follow the work-arounds.
I sort of see what @cmolina is doing but, I don't know what the value of (src) should be in the examples?

Any way we could get a 'beginner' script?

@Choyeongdeok
Copy link

Choyeongdeok commented Apr 26, 2022

@mvaleno In my case, I applied @glen-84 answer in my webpack.dev.js

I used Browser-sync-webpack-plugin in my webpack development, so I added snippetOptions in

plugins: [
    new BrowserSyncPlugin({
        ...,
        snippetOptions: {...},
        ...
    })
]

@shakyShane
Copy link
Contributor

fixed in browser-sync@2.28.0

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

No branches or pull requests

10 participants