Html-webpack-plugin: Option to specify insertion point of a css link tag using mini-css-extract-plugin?

Created on 18 Jul 2019  路  12Comments  路  Source: jantimon/html-webpack-plugin

I understand that this looks like it should be addressed to mini-css-extract-plugin's issues. But it's already been done. They don't seem to agree that it's within their scope to address this.

Do you agree with that? Is there already an option to achieve this with html-webpack-plugin?

All we're asking is an option to specify where we'd want our <link> tag to be inserted in the html template.

Currently it goes in the <head>, and what satisfies my usecase is having the option to insert it at the end of the <body> tag.

Thanx!

Most helpful comment

@Birowsky there is an easy way solution, here you go.

Webpack config

    new HtmlWebpackPlugin({
        inject: false,
        template: '----YOUR-INDEX----',
    }),

For CSS on

        <%= htmlWebpackPlugin.files.css.map(href =>
            '<link href="' + href + '" rel="stylesheet">'
        ).join('\n') %>

For Javascript on

        <%= htmlWebpackPlugin.files.css.map(href =>
            '<script type="text/javascript" src="' + href + '"></script>'
        ).join('\n') %>

All 12 comments

You can set inject:false.

This will disable any modification of your template and allows you to add the link and script tags by yourself.

If you use the build in default template loader this would look like this (simplified):

<html>
<body>
<%= assetTags.headTags %>
<%= assetTags.bodyTags %>
</body>
</html>

headTags contains: an array of link and meta tags
bodyTags contains: an array of script tags

All available parameters are generated here:

https://github.com/jantimon/html-webpack-plugin/blob/075473d2b6507eb278dee2fb4da1c6492f8bf492/index.js#L938-L975

Hey there, thanx a lot for the direction!

Is this possible with v3.2.0?

I tried updating to v4, but I'm using Favicons Webpack Plugin, which is incompatible with it.

@Birowsky there is an easy way solution, here you go.

Webpack config

    new HtmlWebpackPlugin({
        inject: false,
        template: '----YOUR-INDEX----',
    }),

For CSS on

        <%= htmlWebpackPlugin.files.css.map(href =>
            '<link href="' + href + '" rel="stylesheet">'
        ).join('\n') %>

For Javascript on

        <%= htmlWebpackPlugin.files.css.map(href =>
            '<script type="text/javascript" src="' + href + '"></script>'
        ).join('\n') %>

I finally got around trying this, but I'm facing an error:

ERROR in   Error: Child compilation failed:
  Module build failed (from ../node_modules/ejs-compiled-loader/index.js):
  NonErrorEmittedError: (Emitted value instead of an instance of Error) Unexpected token: operator (>) (line: 40, col: 2737, pos: 10104)
  Error
  ```

Here's how my config looks like:

new HtmlWebpackPlugin({
inject: false,
template: './app.ejs',
filename: 'index.html',
})

<details><summary>Further log output</summary>
<p>


  • parse-js.js:263 new JS_Parse_Error
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:263:18

  • parse-js.js:271 js_error
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:271:11

  • parse-js.js:733 croak
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:733:9

  • parse-js.js:740 token_error
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:740:9

  • parse-js.js:746 unexpected
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:746:9

  • parse-js.js:1124
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:1124:9

  • parse-js.js:1209 maybe_unary
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:1209:19

  • parse-js.js:1236 expr_ops
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:1236:24

  • parse-js.js:1240 maybe_conditional
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:1240:20

  • parse-js.js:1264 maybe_assign
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:1264:20

  • parse-js.js:1268 maybe_assign
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:1268:60

  • parse-js.js:1278
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:1278:20

  • parse-js.js:1135 expr_list
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:1135:24

  • parse-js.js:1198 subscripts
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:1198:48

  • parse-js.js:1190 subscripts
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:1190:20

  • parse-js.js:1190 subscripts
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:1190:20

  • parse-js.js:1190 subscripts
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:1190:20

  • parse-js.js:1122
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:1122:20

  • parse-js.js:1209 maybe_unary
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:1209:19

  • parse-js.js:1236 expr_ops
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:1236:24

  • parse-js.js:1240 maybe_conditional
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:1240:20

  • parse-js.js:1264 maybe_assign
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:1264:20

  • parse-js.js:1278
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:1278:20

  • parse-js.js:1281
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:1281:36

  • parse-js.js:1312 prog1
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:1312:15

  • parse-js.js:1104
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:1104:35

  • parse-js.js:1209 maybe_unary
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:1209:19

  • parse-js.js:1236 expr_ops
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:1236:24

  • parse-js.js:1240 maybe_conditional
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:1240:20

  • parse-js.js:1264 maybe_assign
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:1264:20

  • parse-js.js:1278
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:1278:20

  • parse-js.js:1135 expr_list
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:1135:24

  • parse-js.js:1198 subscripts
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:1198:48

  • parse-js.js:1122
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:1122:20

  • parse-js.js:1209 maybe_unary
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:1209:19

  • parse-js.js:1236 expr_ops
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:1236:24

  • parse-js.js:1240 maybe_conditional
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:1240:20

  • parse-js.js:1264 maybe_assign
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:1264:20

  • parse-js.js:1278
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:1278:20

  • parse-js.js:1135 expr_list
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:1135:24

  • parse-js.js:1198 subscripts
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:1198:48

  • parse-js.js:1190 subscripts
    [gotaguy-frontend]/[ejs-compiled-loader]/[uglify-js]/lib/parse-js.js:1190:20

  • NormalModule.js:310 runLoaders
    [gotaguy-frontend]/[webpack]/lib/NormalModule.js:310:13

  • LoaderRunner.js:367
    [gotaguy-frontend]/[loader-runner]/lib/LoaderRunner.js:367:11

  • LoaderRunner.js:233
    [gotaguy-frontend]/[loader-runner]/lib/LoaderRunner.js:233:18

  • LoaderRunner.js:143 runSyncOrAsync
    [gotaguy-frontend]/[loader-runner]/lib/LoaderRunner.js:143:3

  • LoaderRunner.js:232 iterateNormalLoaders
    [gotaguy-frontend]/[loader-runner]/lib/LoaderRunner.js:232:2

  • LoaderRunner.js:205 Array.
    [gotaguy-frontend]/[loader-runner]/lib/LoaderRunner.js:205:4

  • CachedInputFileSystem.js:43 Storage.finished
    [gotaguy-frontend]/[enhanced-resolve]/lib/CachedInputFileSystem.js:43:16

  • CachedInputFileSystem.js:79 provider
    [gotaguy-frontend]/[enhanced-resolve]/lib/CachedInputFileSystem.js:79:9

  • graceful-fs.js:78
    [gotaguy-frontend]/[graceful-fs]/graceful-fs.js:78:16

ERROR in Error: Child compilation failed:
Module build failed (from ../node_modules/ejs-compiled-loader/index.js):
NonErrorEmittedError: (Emitted value instead of an instance of Error) Unexpected token: operator (>) (line: 40, col: 2737, pos: 10104)
Error

ERROR in ./app.ejs (../node_modules/html-webpack-plugin/lib/loader.js!./app.ejs)
Module build failed (from ../node_modules/ejs-compiled-loader/index.js):
NonErrorEmittedError: (Emitted value instead of an instance of Error) Unexpected token: operator (>) (line: 40, col: 2737, pos: 10104)

Error
    at new JS_Parse_Error (/{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:263:18)
    at js_error (/{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:271:11)
    at croak (/{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:733:9)
    at token_error (/{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:740:9)
    at unexpected (/{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:746:9)
    at /{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:1124:9
    at maybe_unary (/{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:1209:19)
    at expr_ops (/{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:1236:24)
    at maybe_conditional (/{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:1240:20)
    at maybe_assign (/{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:1264:20)
    at maybe_assign (/{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:1268:60)
    at /{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:1278:20
    at expr_list (/{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:1135:24)
    at subscripts (/{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:1198:48)
    at subscripts (/{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:1190:20)
    at subscripts (/{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:1190:20)
    at subscripts (/{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:1190:20)
    at /{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:1122:20
    at maybe_unary (/{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:1209:19)
    at expr_ops (/{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:1236:24)
    at maybe_conditional (/{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:1240:20)
    at maybe_assign (/{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:1264:20)
    at /{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:1278:20
    at /{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:1281:36
    at prog1 (/{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:1312:15)
    at /{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:1104:35
    at maybe_unary (/{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:1209:19)
    at expr_ops (/{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:1236:24)
    at maybe_conditional (/{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:1240:20)
    at maybe_assign (/{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:1264:20)
    at /{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:1278:20
    at expr_list (/{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:1135:24)
    at subscripts (/{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:1198:48)
    at /{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:1122:20
    at maybe_unary (/{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:1209:19)
    at expr_ops (/{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:1236:24)
    at maybe_conditional (/{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:1240:20)
    at maybe_assign (/{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:1264:20)
    at /{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:1278:20
    at expr_list (/{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:1135:24)
    at subscripts (/{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:1198:48)
    at subscripts (/{{obfuscated-project-path}}/node_modules/ejs-compiled-loader/node_modules/uglify-js/lib/parse-js.js:1190:20)
    at runLoaders (/{{obfuscated-project-path}}/node_modules/webpack/lib/NormalModule.js:310:13)
    at /{{obfuscated-project-path}}/node_modules/loader-runner/lib/LoaderRunner.js:367:11
    at /{{obfuscated-project-path}}/node_modules/loader-runner/lib/LoaderRunner.js:233:18
    at runSyncOrAsync (/{{obfuscated-project-path}}/node_modules/loader-runner/lib/LoaderRunner.js:143:3)
    at iterateNormalLoaders (/{{obfuscated-project-path}}/node_modules/loader-runner/lib/LoaderRunner.js:232:2)
    at Array.<anonymous> (/{{obfuscated-project-path}}/node_modules/loader-runner/lib/LoaderRunner.js:205:4)
    at Storage.finished (/{{obfuscated-project-path}}/node_modules/enhanced-resolve/lib/CachedInputFileSystem.js:43:16)
    at provider (/{{obfuscated-project-path}}/node_modules/enhanced-resolve/lib/CachedInputFileSystem.js:79:9)
    at /{{obfuscated-project-path}}/node_modules/graceful-fs/graceful-fs.js:78:16
    at FSReqWrap.readFileAfterClose [as oncomplete] (internal/fs/read_file_context.js:53:3)

```

Have you already tried the FaviconsWebpackPlugin 1.0?

Hey @jantimon! Thanx for the suggestion, didn't notice it got updated.

Just tried it, and what I see is that on inject:false, the FaviconsWebpackPlugin tags are not injected in the html file.

Ohh @Birowsky you are right.. sorry for that - there is work on it already in the FaviconsWebpackPlugin master branch

@jantimon I went ahead and tried your suggestion without FaviconsWebpackPlugin, and I got stuff to report:

One of my goals is to inline a splash.css before the main app.css link tag, so that it would end up looking like:

<style>#splash{...}</style>
<link href="app.923680b9da231095ec17.css" rel="stylesheet">

To inline the splash, I'm using HTMLInlineCSSWebpackPlugin.
To sort the chunks to the desired order, I use chunksSortMode:

const chunkOrder = ['splash', 'app'];
...
chunksSortMode: (a, b) => chunkOrder.indexOf(a) <= chunkOrder.indexOf(b) ? -1 : 1,

However, the desired order is not respected. First comes the "app" chunk, then the "splash" chunk. And that's without the suggested inject: false.

On the other hand, if I set inject: false and also set the injecting points in my template down in the <body> like so:

<%- htmlWebpackPlugin.tags.headTags %>
<%- htmlWebpackPlugin.tags.bodyTags %>

the inlined splash css stays in the <head> and the rest of the chunk assets are injected appropriately in the <body>.

This to me indicates some sort of bug when inlining stuff with HTMLInlineCSSWebpackPlugin, I just don't know who to blame ; )


At this point my goal is achieved, and I also understand that the FaviconsWebpackPlugin issue is not related to this plugin, which means this issue is closable. I'll let you take the executive decision tho.

Thanks for your feedback :)

You can also filter on tag e.g.:

<%= htmlWebpackPlugin
  .tags
  .headTags
  .filter((tag) => tag.tagName === 'meta')
  .join('') 
%>

That way you might be able to inject only splash

If you are suggesting this as a workaround, don't worry about it. I'm fine with what I got.

If you are suggesting this as a canonical approach to solving this issue, I'm a bit confused. Aren't we supposed to expect that even the inlined chunks are to be injected at the declared injection point?

image
this maybe can help you
html-webpack-extra-tags-plugin

Was this page helpful?
0 / 5 - 0 ratings

Related issues

lcxfs1991 picture lcxfs1991  路  4Comments

hackteck picture hackteck  路  3Comments

meleyal picture meleyal  路  3Comments

GerkinDev picture GerkinDev  路  3Comments

rokoroku picture rokoroku  路  3Comments