简体   繁体   中英

Can I customize the 'script' tag WebPack inserts?

So I'm new to webpack but read a lot.

There's one task I'm trying to find out if its doable with current code (including plugins etc). We use HtmlWebpackPlugin and providing it with a custom template, asking it to inject the script tag near closing body tag. It works fine but what we want to is to able to control the tag that is being injected into the html template. This is the default tag being used:

<script src="/bundle.js"></script>

We want to have a custom script tag content, instead of the simple script tag, like so:

<script type="text/javascript">
    var bundleUrl;
    if( document.cookie.indexOf('LOCALHOST=')== -1 ){
        bundleUrl="/bundle.js"; // just an example...
    } else {
        bundleUrl = "http://localhost:8080/42565632a54c11195088 .bundle.js"; // use localhost source...
    }
    document.write(unescape('%3Cscript src="' + bundleUrl + '"%3E%3C/script%3E'));
</script>

the above will allow a dynamically altered bundleUrl that is changed at run time according to presence of a cookie.

The reason the above cannot be hard coded into the template is since on production environment, the bundle has a hash prefix... .

The only way I'm aware we can achieve this is by extending HtmlWebpackPlugin, but that's less maintainable.

Suggestions?

TIA!

Temporary solution

Not the prettiest, but it works. I've ended up with just emptying 'chunks' section and inserting my hard coded script tag in the template. Like so:

plugins: [
  new HtmlWebpackPlugin({
    inject:   'body',
    template: 'my-template.html',
    filename: 'index.html',
    chunks: []
})

This effectively have HtmlWebpackPlugin take the source template and transform it, changing nothing inside, yet just putting it as index.html as required to (our environment is slightly more sophisticated).

What template language are you using? I'm not sure on your cookie requirement, but I ended up with this in my template:

{! cant have the hash here when using HMR !}
<script src="js/main{?config.fileHash}.{config.fileHash}{/config.fileHash}.js"></script>

..ie, if config.fileHash exists then print it out, if not then dont

This is using the Dust.js template syntax, but I am sure you could do something similar in others.

in my router:

router.templateConfig = {
  fileHash: null,
};

The fileHash is written to that config on a prod build:

router.templateConfig.fileHash = stats.toJson().hash;

(I used one hash for all the assets, but you could probably use the same technique for per chunk hashes, try logging console.log(stats.toJson())

I do use the HtmlWebpackPlugin injecting the script in my html, to control that I recommend you build it directly from the webpack.config using the node enviroment variable it's really simple and much more efficient.

In your console use:

Mac: export NODE_ENV=production

Windows: set NODE_ENV=production

In your webpack add:

var PROD = process.env.NODE_ENV == 'production';

And in the output you can use this:

 output: {
    filename: PROD ? "[name].min.js" : "[name].js",
  },

In your package.json add the scripts tags, just be sure to use your build commands here:

  "scripts": {
    "watch": "set NODE_ENV=development&&webpack --progress --colors --watch",
    "deploy": "set NODE_ENV=production&&webpack -p"
  },

For prod release I recomend you check the UglifyJsPlugin.

You can have another reference in my answer here: Why is my webpack bundle.js and vendor.bundle.js so incredibly big?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM