momocow / webpack-userscript

A Webpack plugin for userscript projects. 🙈
https://cow.moe/webpack-userscript/
MIT License
200 stars 21 forks source link

Improve documentation #12

Closed okoetter closed 5 years ago

okoetter commented 5 years ago

Hi,

just discovered this webpack plugin and it may be exactly what I need. However I have a hard time finding out the intended workflow (I use Tampermonkey in Google Chrome on Windows 10), so I have two questions regarding "Hot Development":

1.) You wrote that webpack-dev-server will build the userscript in watch mode. How do you run webpack-dev-server? Simply call it on the command line? Which arguments? Usually I insert a script key to package.json to use npm run dev or something like that to run webpack-dev-server --mode=development --hide-modules --devtool inline-source-map --hot. I learned that both --devtool inline-source-map and --mode=development blows up my generated user.js to >1 MB and that lets the browser freeze. Without those arguments it seems to work, but that means production mode and my js is minimized.

2.) I use this in my webpack.config.js:

plugins: [
    new WebpackUserscript({
      metajs: true,
      headers: {
        "name": "Test",
        "version": dev ? "[version]-build.[buildNo]" : "[version]",
        "downloadURL":  "https://mydomain/Test/Test.user.js",
        "updateURL": "https://mydomain/Test/Test.meta.js",
        "match": "*",
        "grant": [
          "GM.getValue",
          "GM.setValue",
          "GM.deleteValue"
        ]
      },
      pretty: true
    })
  ]

As far as I understand that leads to an increasing buildNo and therefor version number everytime I save my script and webpack-dev-server watching it compiles it? At the beginning I installed the script from http://localhost:8080/Test.user.js but what if a new version has been compiled? Do I need to instruct Tampermonkey to look for updates then? In my case Tampermonkey does not find a new version. Maybe I may not use downloadURL and updateURL headers because they point to different URLs?

Could you please share how exactly you are working or how this is intended to use?

momocow commented 5 years ago

For your question 1, actually I think the arguments of webpack-dev-server are all up to you.

The point here is that a HTTP server is required to host your userscript. Luckily webpack-dev-server can serve it for you with additional functionalities like rebuilding the userscript when source files are changed.

In the old workflow, when developing userscript, people usually just copy their source code and paste it to the TamperMonkey editor panel. The webpack-dev-server (or any other HTTP server) provides another way to transport the source code to TamperMonkey; that is, to install the userscript via URL.

momocow commented 5 years ago

For question 2,

As far as I understand that leads to an increasing buildNo and therefor version number everytime I save my script and webpack-dev-server watching it compiles it?

Yes, the build number increases when the userscript is compiled and the compilation is triggered by saving on source files.

Do I need to instruct Tampermonkey to look for updates then?

Yes, you need to click on the recent update field and TamperMonkey will do the update for you. image

In my case Tampermonkey does not find a new version. Maybe I may not use downloadURL and updateURL headers because they point to different URLs?

It's actually the issue of how TamperMonkey detects version changes. If your https://mydomain/Test/Test.meta.js does not contain a version high than your installed one, it is expected to have no update.

okoetter commented 5 years ago

Thanks for your answers. Regarding 2: What would be needed then is a method to distinguish the dev mode so that the metadata "downloadURL" and "updateURL" are not written to the user script (or include the dev localhost url ) and a production mode, so when I do e.g. a npm run build the two metadata tags are actually written.

momocow commented 5 years ago

Usually, people use the environment variable NODE_ENV set to production or development to distinguish which mode should be used under current environment.

You can take a look at the example of Hot Development, especially how dev variable is determined and is used.

new WebpackUserscript({
      headers: {
        version: dev ? `[version]-build.[buildNo]` : `[version]`
      }
    })
okoetter commented 5 years ago

OK, I got it to work.

But this code from your example does not work in webpack 4.32.2 which I was using:

const dev = process.env.NODE_ENV === 'development'

process.env.NODE_ENV is always undefined.

What works for me:

module.exports = (env, argv) => ({
  mode: argv.mode,
  ...
  plugins: [
    new WebpackUserscript({
      headers: {
        "name": argv.mode === "development" ? "Test-Debug" : "Test",
        "version": argv.mode === "development" ? "[version]-build.[buildNo]" : "[version]",
        "downloadURL": argv.mode === "development" ? "" : "https://mydomain/Test/Test.user.js",
        "updateURL": argv.mode === "development" ? "" : "https://mydomain/Test/Test.meta.js",
        "grant": [
          "GM.getValue",
          "GM.setValue",
          "GM.deleteValue"
        ]
      },
    })
  ]
});

Setting downloadURL and updateURL empty in dev mode leads to not outputting these meta tags in dev mode, so hot module updating works now.

momocow commented 5 years ago

argv is also a feasible way.


But!

process.env.NODE_ENV is always undefined.

That's just as expected since the NODE_ENV environment variable should never be set by any framework but yourself.

I assume that you are not familiar with some of the NodeJS conventions, I suggest you to do more search about NODE_ENV, or at least read this one.

If your system is Linux, you can export the NODE_ENV set to "development" or "production" via

export NODE_ENV=production

in your system, or you can set it per command, for example,

NODE_ENV=production webpack-dev-server

Put this command in the scripts field of package.json will also works if you run the script on Linux, for Windows, try cross-env.

Note that the NODE_ENV variable only exists during this runtime of webpack-dev-server.

okoetter commented 5 years ago

OK, I assumed that NODE_ENV is set to either development or production automatically if you call webpack-dev-server with --mode=development or --mode=production (just during runtime of webpack-dev-server of course).

Either way it works fine for me now. Thanks a lot for a great plugin!

momocow commented 5 years ago

Happy scripting!

georgms commented 5 years ago

Really love this project and sorry for resurrecting this post – with the config described here updating the build number works fine, my webpack-dev-server is always serving the latest version and the page is reloaded when I make a change to my script.

However, I have to manually instruct TamperMonkey to update the userscript by clicking on the "last update" timestamp for my userscript. Is there a way to get TamperMonkey to always fetch the latest version when reloading the page, without having to manually click on the update button ("last update" timestamp)?

georgms commented 5 years ago

A nasty work around I am using for now:

I have created another userscript with a @require directive that points to my userscript, eg. // @require https://localhost:8080/my-userscript.user.js. The trick is to make sure TamperMonkey does not cache externals, can be configured as described in https://github.com/Tampermonkey/tampermonkey/issues/475. However, I still need to reload the page twice to receive the update.

momocow commented 5 years ago

@georgms Sorry but I have not found any way to force Tampermonkey update the script on each page load either. BTW, why the page reload should be twice to receive the update?

georgms commented 5 years ago

@momocow

BTW, why the page reload should be twice to receive the update?

I really don't know but that's the way it is for me. Sometimes I have to reload three times so it's probably a matter of how long I wait rather than how often I reload.

Anyway, this method works sufficiently well for me. Maybe it's something to add to the docs?