Chrome can't load web worker
Asked Answered
G

16

147

I am working on a project that uses a web worker.

In my head section I have this code:

var worker = new Worker("worker.js");
// More code

This works fine in Safari, but Chrome reports the following error:

Uncaught SecurityError: Failed to create a worker: script at '(path)/worker.js' cannot be accessed from origin 'null'.

Why does this work perfectly in Safari but not Chrome? How do I fix this?

Thank you.

Grassi answered 28/1, 2014 at 14:36 Comment(3)
Are you working off the file protocol? If you are set the access flag and see if it works: #18587421Iodine
Yes, the path for the web worker is this: file:///E:/programming/web/project/worker.js. The path for the main project is this: file:///E:/programming/web/project/index.html.Grassi
Try this: #18587421Iodine
E
124

Chrome doesn't let you load web workers when running scripts from a local file.

Effete answered 21/4, 2014 at 22:9 Comment(5)
From this answer, Loading a local file, even with a relative URL, is the same as loading a file with the file: protocol. -- and it's not cool for web pages to be able to just access your file system on a whim.Niles
-1 firsfox will let you do this of course, provided you're also using file as a origin (eg. you're viewing local file in browser). It's just chrome that is broken.Kulp
Firefox still works (yes from file://), Chrome does not in this case.Dnieper
There are numerous workarounds like setting the flag in chrome settings, using a local server instead of directly accessing html or injecting the worker.Essayist
UPDATE: the latest version of Firefox (v120) also disallows on the same basis, even via the file protocol. You can run Workers fine locally from a web server like Tomcat, but not from a local file.Albie
V
73

I use a workaround. Chrome blocks Worker but not <script>. Hence the best way to make a universal solution is this:

function worker_function() {
    // all code here
}
// This is in case of normal worker start
// "window" is not defined in web worker
// so if you load this file directly using `new Worker`
// the worker code will still execute properly
if(window!=self)
  worker_function();

You then link it as normal <script src="...". And once the function is defined, you use this abomination of a code:

new Worker(URL.createObjectURL(new Blob(["("+worker_function.toString()+")()"], {type: 'text/javascript'})));
Volney answered 30/10, 2015 at 9:5 Comment(13)
This solution is good. why in this world nothing is perfect? Every software is agitating the users with bugs,flaws,childish-behaviors etc. Firefox is also arrogant as it refuses to support "clip-path" css property.Rapture
I am not a js dev and don't get the point of the script tag use here. And what is the window != self check for? Can someone please explain this loading sequence? Thx.Alvaroalveolar
Script tags will be loaded by google chrome if they are in the same directory as HTML. window!=seld checks whether the code is running in web worker. This makes this code portable in case you load the javascript file directly in other contexts.Kulp
@TomášZato you mean if window != self is true, code is executing in webworker context? I was googling around and couldn't find this kind of check.Alvaroalveolar
Then google what window and self variables mean in javascript. You'll see that window is not defined in web workers.Kulp
dumb question, but i'm fairly new to web workers... what goes in the 'worker_function'? thanks...Ras
@Ras The code that should execute in web worker context.Kulp
I should note that you can't use importScript from a worker written like this. At least, not without an additional workaround. So you'll need more tampering for a multi-file worker.Yuan
how do u debug this code, if it is converted by blob?Bristling
@TomášZato thanks for this workaround, but how do you pass arguments to the worker? Before is use BackgroundWorker.postMessage(xArgs);. The postMessage function is still the trigger for the worker, but the xArgs do not get passed. Is there a aprouch to pass arguments to worker with this workaround? My console.log looks like Blob {size: 1420, type: "text/javascript"} WorkerMain.js:17, blob:null/94d14ccf-19a8-4322-aff9-9519ab9359d8 WorkerMain.js:21, {array: Array(16)} (the argument which should passed) blob:null/94d14ccf-19a8-4322-aff9-9519ab9359d8:3 WORKER START undefinedSpile
@MarTin You're probably doing something wrong. You should ask a separate question about not being able to postMessageKulp
I also noticed that, but stringify the variable to pass (json) var json = JSON.stringify(xJsonArgs); and than pass like new Worker(URL.createObjectURL(new Blob([(${xFunction.toString()})(${json})], { type: 'text/javascript' }))); works for me. Thanks for your response.Spile
I get this error ERROR DOMException: Failed to construct 'Worker': Access to the script at 'blob:*****' is denied by the document's Content Security Policy.Haworth
W
56

The problem has been properly explained by Noble Chicken but I have a more general solution for it. Instead of installing wamp or xamp, with python you can navigate to the folder your project is hosted in and type: python -m http.server

Just that and you will have a running server on that folder, reachable from localhost.

Wherein answered 17/6, 2014 at 15:8 Comment(4)
Macs will probably need to go with python -m SimpleHTTPServer 8000 as they're loaded with < Python 3 (just to save another google search :D)Shit
you can also install the http-server node module and then navigate to the desired folder from the terminal and run 'http-server -p 3000'.Bastinado
worth to mention this script "python -m http.server" need Python 3.Gerald
Also try php -S localhost:8000Plafond
E
38

You can also use the --allow-file-access-from-files flag when you launch Chrome.

Example for MacOsX :

/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --allow-file-access-from-files

More info : Web worker settings for chrome

Ethben answered 17/2, 2016 at 18:10 Comment(5)
On windows command window navigate to: "C:\Users\NAME\AppData\Local\Google\Chrome SxS\Application", then run chrome.exe --allow-file-access-from-files, then copy your local file path e.g. c:\temp\myWeb\index.html and paste into the url of the opened browser, done.Gerald
You can also create a shortcut and pass the flag in the target path.Originate
Oh, and from the linked question, remember to close all Chrome windows before launching with the flag.Originate
Yep, an other option can also be to code a Chrome Extension with right permission in it's manifest : "permissions": ["file://*/*"], like in #19493520Lashoh
Note: "You have to close all the windows of Chrome before opening it with --allow-file-access-from-files flag on." as stated on https://mcmap.net/q/160742/-web-worker-settings-for-chromeIncommutable
C
20

It is because of the security restrictions. You need to use http:// or https:// protocol instead of file:///.

If you have NodeJS installed, you can simply do the following. - Note that this is one of many options available

Install local-web-server

$ npm install -g local-web-server

Now you can use it in any folder that you want to access the contents through http .

$ ws

Navigate to http://localhost:8000 (default port: 8000)

Coniology answered 19/6, 2016 at 17:21 Comment(0)
O
8

I had the same problem as your post too. The solution is that you have to run it with localhost (wamp or xamp). It will done.

Outside answered 22/4, 2014 at 2:47 Comment(1)
Wow, I never would have found this -- thanks! (I hope thanks are allowed in comments)Guelph
S
7

Another workaround is use Google's web server for Chrome extension. Choose your work directory and start the server, Done!

Sawhorse answered 11/3, 2018 at 16:3 Comment(0)
C
7

This is inspired by Thomas answer above. But with one caveat that I wanted to distribute only the HTML, so i manually converted the js to dataURL. and enabling the data URL check box in it.

const myWorker = new Worker("data:application/x-javascript;base64,b25tZXNzYW...");
Cozart answered 27/12, 2019 at 11:16 Comment(0)
L
6

Easy way to make local http server in chrome is this app:

Web Server for Chrome

https://chrome.google.com/webstore/detail/web-server-for-chrome/ofhbbkphhbklhfoeikjpcbhemlocgigb/related

Description:

A Web Server for Chrome, serves web pages from a local folder over the network, using HTTP. Runs offline. Web Server for Chrome is an open source (MIT) HTTP server for Chrome.

It runs anywhere that you have Chrome installed, so you can take it anywhere. It even works on ARM chromebooks.

It now has the option to listen on the local network, so other computers can access your files. Additionally, it can try and get an internet address.

Many people use this to do basic web development on a chromebook. It is also handy for sharing files over a local network between computers, or even on the internet.

Once you install it, navigate to http://127.0.0.1:8887

And it is not unsecure as flag --allow-file-access-from-files

Lysippus answered 24/1, 2019 at 20:8 Comment(1)
This is amazing! I can now run my reactJS app with web workers from local file system. Can't be much easier!Sissified
U
4

you need a web server for request from HTTP protocol Instead of local file and work correctly :)

Underdog answered 4/4, 2015 at 9:24 Comment(1)
No you don't. You need to ignore browsers that do not follow web standards just because they are mainstream.Kulp
T
3

Chrome load the file but cannot run it. Use Firefox. It's working for me.

Tanagra answered 16/10, 2015 at 18:28 Comment(2)
To explain my downvote: This might be better off starting with a comment, perhaps inquiring more about their browser support requirements, rather than being submitted as the answer. It seems quite likely not an answer, given what the user has already said about cross-browser support.Amortizement
If you've read the question carefully I'm sure that you'll not down vote the response as three before you up vote it! The user is saying that Chrome can't load the worker. No, chrome can load the worker but can't run it. The reasons why I put it as a response is first the question is asked one year ago and the second many responses are saying that Firefox is not running the worker which I can't comment all of them. I'm just explaining but you've right to down vote or up vote.Tanagra
B
2

With Python 2.x being more widely deployed than Python 3.x, something like python -m SimpleHTTPServer 8000 is more generally applicable, and not just for Mac OS X. I found it necessary for use under Cygwin, for instance.

With that in place, this example worked like a champ.

Besse answered 15/10, 2015 at 17:32 Comment(0)
S
2
function worker_fun(num){
    num ++
    // console.log(num)
    postMessage(num);
    setTimeout(worker_fun.bind(null,num), 500)
}

var w

function startWorker(){
    var blob = new Blob([
        "onmessage = function(e){\
            " + worker_fun.toString() + "\
            worker_fun(e.data.num);}"
    ]);
    var blobURL = window.URL.createObjectURL(blob);
    if (typeof(Worker) != 'undefined'){
        if (typeof(w) == 'undefined'){

            w = new Worker(blobURL);
            w.onmessage = function(event){
                document.getElementById('num').innerHTML = event.data;
            } 
            w.postMessage({
               num:parseInt(document.getElementById('num').innerHTML)})
        }
    }
}


function stopWorker() { 
    w.terminate();
    w = undefined;
}

As mentioned chrome does not support it. I like to define my workers in the same file. This is a working workaround which will increase a number found in innerHTML of the element the with id=num every 500ms.

Selhorst answered 9/12, 2018 at 23:57 Comment(0)
N
1

A probably reason is chrome doesn't let you load web workers when running scripts from a local file. And I try run the code on my firefox, can not either.

Neckwear answered 10/4, 2016 at 11:33 Comment(1)
Web Workers running fine on file:// in Firefox 51.0.1Lenwood
M
0

To load web worker from file in a project set up with Webpack and TypeScript I used a script as Tomáš Zato suggested. However, I had to modify the worker file.

worker.ts

(() => {
    console.log("worker_function loaded");
    // @ts-ignore
    window.worker_function = () => {
        self.onmessage = ({ data: { question } }) => {
            // @ts-ignore
            self.postMessage({
                answer: 42,
            });
        };
    }
})();

index.ts

async function run() {
    console.log('run()');

    const worker = new Worker(
        // @ts-ignore
        URL.createObjectURL(new Blob(["("+worker_function.toString()+")()"], { type: 'text/javascript' }))
    );

    worker.postMessage({
        question: 'The Answer to the Ultimate Question of Life, The Universe, and Everything.',
    });
    worker.onmessage = ({ data: { answer } }) => {
        console.log(answer);
    };
}

run();

index.html

<html lang="en-us">
  <head>
    <meta charset="utf-8" />
    <meta content="text/html; charset=utf-8" http-equiv="Content-Type" />
    <title>Offscreen canvas with web worker sample project</title>
    <script async type="text/javascript" src="worker.js"></script>
    <script async type="text/javascript" src="app.js"></script>
  </head>
  <body>
    <h1>web worker sample project</h1>
  </body>
</html>

webpack.config.js (version 5)

const path = require("path");
const CopyPlugin = require("copy-webpack-plugin");

module.exports = {
  mode: "production",
  entry: {
    app: "./src/index.ts",
    worker: "/src/worker.ts"
  },
  output: {
    filename: "[name].js",
    path: path.resolve(__dirname, "build")
  },
  performance: {
    hints: false
  },
  module: {
    rules: [
      {
        test: /\.tsx?$/,
        use: "ts-loader",
        exclude: /node_modules/
      },
    ]
  },
  resolve: {
    extensions: [".js", ".ts"]
  },
  plugins: [
    new CopyPlugin({
      patterns: [
        { from: "src/index.html", to: "" }
      ]
    })
  ]
};
Marlow answered 19/12, 2021 at 11:32 Comment(0)
P
-7

Yes, It will not work in chorome if your are loading local file. But it will work fine in firefox browser. And you have to add below code in HTML file.

<head>
    <meta charset="UTF-8" />
</head>
Pity answered 13/2, 2018 at 15:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.