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

js file is not injected, but css file is injected to the template with 4.0.0-beta.11 version. #1355

Closed
wdkdyd opened this issue Mar 9, 2020 · 20 comments · Fixed by #1386
Closed

Comments

@wdkdyd
Copy link

wdkdyd commented Mar 9, 2020

new HtmlWebpackPlugin({
        filename: `${filePath + chunkName}.html`,
        template: `${ item }/${ chunkName }.html`,
        chunks: ['common'],
        cache: true,
        hash:true,
        inject: true
   });
@jantimon
Copy link
Owner

jantimon commented Mar 9, 2020

The filtering is happening here:

const filteredEntryNames = self.filterChunks(entryNames, self.options.chunks, self.options.excludeChunks);

can you please add the following code just bellow that line to see what is happening?
you will find it here: node_modules/html-webpack-plugin/index.js

console.log({entryNames, chunks: self.options.chunks, filteredEntryNames});

@wdkdyd
Copy link
Author

wdkdyd commented Mar 9, 2020

{ entryNames:
[ 'common/common',
'private_show' ],
chunks: [ 'common/common', 'private_show' ],
filteredEntryNames: [ 'common/common', 'private_show' ] }

@jantimon
Copy link
Owner

jantimon commented Mar 9, 2020

But that seems to be the correct output right?

Especially this part:

chunks: [ 'common/common', 'private_show' ],
filteredEntryNames: [ 'common/common', 'private_show' ]

In the next step it will turn 'common/common', 'private_show' into the related files:

// Turn the entry point names into file paths
const assets = self.htmlWebpackPluginAssets(compilation, childCompilationOutputName, sortedEntryNames);

Which is asking webpack for the related assets:

const entryPointFiles = compilation.entrypoints.get(entryName).getFiles();

Maybe you can also add a console.log at those places?

@wdkdyd
Copy link
Author

wdkdyd commented Mar 9, 2020

'entryPointFiles':[ 'css/private_show.css', 'js/private_show.js?4c019fd5' ]
'assets' : { publicPath: '//xxx.com/',
js: [],
css: [ '//xxx.com/css/private_show.css?4c019fd5a9695d35bbd6' ],
manifest: undefined,
favicon: undefined }

@jantimon
Copy link
Owner

jantimon commented Mar 9, 2020

Okay so here it looks wrong - it should add the js file.

Even question marks should be supported:

const extensionRegexp = /\.(css|js|mjs)(\?|$)/;

Can you please also add a console.log here?

const extMatch = extensionRegexp.exec(entryPointPublicPath);

console.log({extensionRegexp, entryPointPublicPath})

@wdkdyd
Copy link
Author

wdkdyd commented Mar 9, 2020

{ extensionRegexp: /.(css|js|mjs)(?|$)/,
entryPointPublicPath: '//xxx.com/css/private_show.css?4c019fd5a9695d35bbd6' }

@jantimon
Copy link
Owner

jantimon commented Mar 9, 2020

Does that mean the loop is executed only once? 🤔
Do you have any guess where the data is disappearing?

@wdkdyd
Copy link
Author

wdkdyd commented Mar 9, 2020

I console in the loop
const extMatch = extensionRegexp.exec(entryPointPublicPath);
console.log(extMatch)

and i got

null
null
[ '.css?',
'css',
'?',
index: 28,
input: '//xxx.com/css/private_show.css?4c019fd5a9695d35bbd6',
groups: undefined ]

the two null means these two js file not match?

@wdkdyd
Copy link
Author

wdkdyd commented Mar 9, 2020

i find it, because of add hash after js filename

/.(css|js|mjs)(?|$)/.exec('css/private_show.css')
(3) [".css", "css", "", index: 16, input: "css/private_show.css", groups: undefined]
/.(css|js|mjs)(?|$)/.exec('js/private_show.js?4c019fd5')
(3) [".js?", "js", "?", index: 15, input: "js/private_show.js?4c019fd5", groups: undefined]
/.(css|js|mjs)(?|$)/.exec('js/private_show.js')
(3) [".js", "js", "", index: 15, input: "js/private_show.js", groups: undefined]

@jantimon
Copy link
Owner

jantimon commented Mar 9, 2020

Sorry I can't follow - why would const extensionRegexp = /\.(css|js|mjs)(\?|$)/; not work for 'js/private_show.js?4c019fd5'?

@wdkdyd
Copy link
Author

wdkdyd commented Mar 9, 2020

/js/private_show.js%3F3252aa
the ? has been encodeURIComponent to %3F ,so didnot match? maybe you should decodeURIComponent entry first?

@jantimon
Copy link
Owner

jantimon commented Mar 9, 2020

Okay that makes sense - where does the encoded ? come from?

Would changing

const extensionRegexp = /\.(css|js|mjs)(\?|$)/;

to

const extensionRegexp = /\.(css|js|mjs)(\?|\%3F|$)/;

solve your problem?

regexper

@wdkdyd
Copy link
Author

wdkdyd commented Mar 11, 2020

sorry for late reply, the "?" is from "output:[name].js?[hash]" , i remove the "?[hash]" , and then it's ok, thank you so much

@jantimon

This comment has been minimized.

@jantimon
Copy link
Owner

jantimon commented Mar 30, 2020

It looks like the reason is this change by @zbigg who tried to allow + inside the url:

35a1541

#1257
#1254

We could switch to encodeURI however it will not encode reserved characters (";,/?:@&=+$";) according to spec:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent

@zbigg Why can you remember why we needed to escape +?

@zbigg
Copy link
Contributor

zbigg commented Mar 30, 2020

@jantimon Well, my reasoning was that webpack works on "files", while html-webpack-plugin uses these files in HTML ans HTML expects URLs which shall be encoded.

TLDR That is not neccessarily true.

Now, looking at webpack documentation and this issue i see great impedance mismatch in meaning of "filename"
Some treat output as URL, some treat output as filename (this doc doesn't refer to URL at all.

So, looks like something that was expected to be filename was accidentally retrofitted to be "URL or filename"

webpack is correctly removing the querystring before it writes files to disk however it is also encaping ? to %3F.

(webpack/webpack#10638)

I would argue that it's not very correct, where you call something "filename" and then attempt to parse it as URL.

Nonetheless, giving that loads of people are relying on this behaviour, it's probably better to revert #1257 and document that "filename" is actually something between filename and URL and should be treated with care.

@imjeen

This comment has been minimized.

@jantimon
Copy link
Owner

jantimon commented Mar 31, 2020

@zbigg I am totally with you people are misusing the output.filename option (some add question marks others add plus signs).

This has never been a supported or unit tested feature but a hack that worked because luckily webpack removes the querystring correctly before writing to disk.

But unfortunately people used this hack a lot and therefore we should probably allow to reuse it also for the new major release.

on the other hand your pull request allowed to use the following questionable characters for filenames:

# pound
% percent
& ampersand
{ left curly bracket
} right curly bracket
\ back slash
< left angle bracket
> right angle bracket
* asterisk
? question mark
/ forward slash
blank spaces
$ dollar sign
! exclamation point
' single quotes
" double quotes
: colon
@ at sign
+ plus sign
backtick
| pipe
= equal sign

so the combination of both features would allow:

some/path?abc/xy+z/fancy.html?abc=foo#top

which should probably be converted to:

some/path%3Fabc/xy%2Bz/fancy.html?abc=foo#top

or am I wrong?

@jantimon
Copy link
Owner

jantimon commented Apr 1, 2020

@zbigg what do you think about #1386 ?

jantimon added a commit that referenced this issue Apr 1, 2020
jantimon added a commit that referenced this issue Apr 1, 2020
jantimon added a commit that referenced this issue Apr 1, 2020
@jantimon
Copy link
Owner

jantimon commented Apr 1, 2020

Released as html-webpack-plugin 4.0.4

@lock lock bot locked as resolved and limited conversation to collaborators May 5, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants