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

Wildcard not matched, instead simply outputted in template #19

Closed
kroko opened this issue Jan 24, 2018 · 8 comments
Closed

Wildcard not matched, instead simply outputted in template #19

kroko opened this issue Jan 24, 2018 · 8 comments

Comments

@kroko
Copy link

kroko commented Jan 24, 2018

Hi,

I have a setup very similar to first example in the docs

  • File calledpreflight.js exists and that is not (and should be not) added in webpack entry.
  • It is copied to webpack configs output path using copy-webpack-plugin. On the way it receives hashing for filename itself which will change only when contents change.
  • I am using html-webpack-plugin to generate template, i this example auto injecting default one.
  • Accordingly to docs I specify minimatch ready string preflight.*.js which would match stuff in webpack's output path (in my case path: path.join(__dirname, 'public/assets'))

I tried both

  • **/*preflight.*.js
  • preflight.*.js

My test config is

// this copies file from 'src/preflight.js to public/assets/preflight.hash.js
config.plugins.push(new CopyWebpackPlugin([
  {
    from: 'src/preflight.js',
    to: `[name].[hash].[ext]`
  }
]));

config.plugins.push(new HtmlWebpackPlugin({
  title: `TEST`,
  filename: `${path.join(__dirname, 'public')}/index.html`,
  inject: true,
  hash: false,
  cache: true,
  showErrors: true,
  chunksSortMode: 'auto',
  excludeChunks: [],
  xhtml: false,
  alwaysWriteToDisk: true,
  minify: false
}));

config.plugins.push(new HtmlWebpackHarddiskPlugin());

config.plugins.push(new HtmlWebpackIncludeAssetsPlugin({
  assets: [
    'preflight.*.js'
  ],
  append: false,
  hash: false
}));

Template output (prod build, not devserver) is

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>TEST</title>
  <link href="//webpacktest-codesplitting.test/assets/site.3c550d0e6ef1b0cc4345.css" rel="stylesheet"></head>
  <body>
<script type="text/javascript" src="//webpacktest-codesplitting.test/assets/preflight.*.js"></script><script type="text/javascript" src="//webpacktest-codesplitting.test/assets/manifest.27fead361ac3388ca95d.js"></script>
<script type="text/javascript" src="//webpacktest-codesplitting.test/assets/vendor.d52f339f6cf1da9e710d.js"></script>
<script type="text/javascript" src="//webpacktest-codesplitting.test/assets/site.3c550d0e6ef1b0cc4345.js"></script>
</body>
</html>

Whatever I put into assets key is outputted as is within template. As you can see from sourcefile name I am testing code splitting 😄 . Disabling that does not change anything.

What am I missing? Did I overlook the docs and there is no actual minimatching against real files in filesystem that are copied over to output path?

Thanks!

software version(s)
node 8.9.4
npm 5.6.0
Operating System macOS 10.13.2
Webpack 3.10.0
copy-webpack-plugin 4.3.1
html-webpack-plugin 2.30.1
html-webpack-harddisk-plugin 0.1.0
html-webpack-include-assets-plugin 1.0.2
@jharris4
Copy link
Owner

The last time I looked into this, the issue was because the copy-webpack-plugin was not copying the assets until AFTER the html-webpack-plugin (and therefore this plugin) had completed processing.

This makes it impossible to do anything other than look at the source files to do minimatching.

At the time I last looked into this, development on the copy-webpack-plugin had mostly stopped but it has since been taken over by the webpack team so maybe they'll be able to make the changes to better support the HtmlWebpackPlugin. There is not much that can be done without that... :-(

Here are some issues that are related:
webpack-contrib/copy-webpack-plugin#133
webpack-contrib/copy-webpack-plugin#15

@kroko
Copy link
Author

kroko commented Jan 24, 2018

Understood.
I'll give Webpack File Manager Plugin a try and report back how it goes.

@kroko
Copy link
Author

kroko commented Jan 24, 2018

Well, combination with filemanager-webpack-plugin does not work too.

If I change CopyWebpackPlugin in the original post to

// ----------------
// FileManagerPlugin

config.plugins.push(new FileManagerPlugin({
  onStart: {
    copy: [
      {
        source: 'src/preflight.js',
        destination: 'public/assets/preflight.123.js'
      }
    ],
    move: [],
    delete: [],
    mkdir: []
  },
  onEnd: {}
}));

I can observe that file emitting really differs, preflight.123.js is the first thing to arrive in output path.

However compiled HTML still contains not resolved minimatch against preflight.123.js (contains raw string as specified in HtmlWebpackIncludeAssetsPlugin assets key).

<script type="text/javascript" src="//webpacktest-codesplitting.test/assets/preflight.*.js">

@kroko
Copy link
Author

kroko commented Jan 24, 2018

If I strip this aspect of before/after

the issue was because the copy-webpack-plugin was not copying the assets until AFTER the html-webpack-plugin (and therefore this plugin) had completed processing.

by

  • dropping file copying in webpack config entirely (both CopyWebpackPlugin and FileManagerPlugin)
  • manually placing 'public/assets/preflight.123.js', so that the file physically really is there from the beginning of the universe as far as code is concerned
  • disabling output path cleanup before building (auto cleaning public/assets/ directory)
  • building the solution

HtmlWebpackIncludeAssetsPlugin still does not find preflight.123.js by specifying assets: ['preflight.*.js'] although examples in your documentation imply that assets string will be matched against everything that is in webpack's output path if relative path is used.

And if I place files

  • preflight.123.js as public/assets/preflight.123.js (thus in output path)
  • preflight.456.js as src/preflight.456.js (thus in src path)

and do either of the following absolute matching approaches

config.plugins.push(new HtmlWebpackIncludeAssetsPlugin({
  assets: [
    `${path.join(__dirname, 'src')}/preflight.*.js`,
    `${path.join(__dirname, 'public/assets')}/preflight.*.js`
  ],
  append: false,
  hash: false
}));

HTML output is still in line with appending raw string that was specified in assets key

<script type="text/javascript" src="//webpacktest-codesplitting.test/assets//Users/myuser/path/to/webpacktest-codesplitting/src/preflight.*.js"></script><script type="text/javascript" src="//webpacktest-codesplitting.test/assets//Users/myuser/path/to/webpacktest-codesplitting/public/assets/preflight.*.js"></script>

Am I doing something wrong or is this broken (considering that there is no copying involved, files exist in filesystem).

@jharris4
Copy link
Owner

Sorry, it's a bit hard for me to follow your examples. Do you think you could create a reproduction of the problem so I can take a quick look?

@kroko
Copy link
Author

kroko commented Feb 6, 2018

Hi,

I revisited this issue - my bad.
I had the assumption that if strings are supplied to assets, then matching will also be done. However it is done only when objects are passed to assets.

Thus to make it work I use FileManagerPlugin to copy files to webpack's output path. It does it onStart. In my example src/preflight/preflight.{js|css} is copied to public/assets/preflight.123.{js|css} (public/assets/ is webpack's output path).

And instead of trying to match those files in output path using

config.plugins.push(new HtmlWebpackIncludeAssetsPlugin({
  assets: [
    'preflight.*.js',
    'preflight.*.css'
  ]
}));

the way I did in original post #19 (comment) and later comment #19 (comment)
I have to do

config.plugins.push(new HtmlWebpackIncludeAssetsPlugin({
  assets: [
    {
      path: '',
      glob: 'preflight.*.js',
      globPath: outputPath
    },
    {
      path: '',
      glob: 'preflight.*.css',
      globPath: outputPath
    }
  ]
}));

outputPath is webpack's output directory.

It works.


And FYI.

I can use it only for case where

  • Have files copied (not built / included in webpack runtime) to output directory
  • Have them referenced in built HTML using HtmlWebpackPlugin

The other need

  • Have files copied (not built / included in webpack runtime) to output directory
  • Have them inlined in built HTML using HtmlWebpackPlugin

will not work. by having script-ext-html-webpack-plugin set up to inline this preflight asset

config.plugins.push(new ScriptExtHtmlWebpackPlugin({
  inline: [
    /preflight.*.js$/
  ]
}));

it will throw ERROR in Error: ScriptExtHtmlWebpackPlugin: no asset with href 'preflight.123.js'

It knows that the file is called 'preflight.123.js', so it reads out HtmlWebpackPlugin assets list. My guess is that the error arises because the actual contents of preflight.123.js are not in-memory (because it is just copied file, it is not built) therefore ScriptExtHtmlWebpackPlugin cannot inline it.

There is ticket for ScriptExtHtmlWebpackPlugin numical/script-ext-html-webpack-plugin#13.

script-ext-html-webpack-plugin is the plugin I use for inlining manifest/runtime in HTML when splitting code using CommonsChunkPlugin and it works.

My current sollution if I want to

  • Have files copied (not built / included in webpack runtime) to output directory
  • Have them inlined in built HTML using HtmlWebpackPlugin

is to have custom keys in HtmlWebpackPlugin that have values of contents I want to inline

config.plugins.push(new HtmlWebpackPlugin({
  fsInlineContents: {
    'preflight.js': fs.readFileSync(path.join(__dirname, 'src/preflight/preflight.js'), 'utf8'),
    'preflight.css': fs.readFileSync(path.join(__dirname, 'src/preflight/preflight.css'), 'utf8')
  }
}));

and then in template I echo the contents out by doing

<script><%= htmlWebpackPlugin.options.fsInlineContents['preflight.js'] %></script>
<style><%= htmlWebpackPlugin.options.fsInlineContents['preflight.css'] %></style>

I haven't tried if html-webpack-inline-source-plugin could make me abandon fs.readFileSync, from the first look it also expects assets that are piped through webpack's build system, not external files, aaand it yould be yet another plugin to manage 😄

@jharris4
Copy link
Owner

jharris4 commented Feb 6, 2018

Yeah, it gets tricky when you're dealing with assets that are being copied to the webpack output path. You need to make sure those assets are copied before htmlWebpackPlugin starts processing things or else you start to get unexpected results...

Thanks for documenting your findings, and for the suggestions of using htmlWebpackPlugin.options.fsInlineContents or ScriptExtHtmlWebpackPlugin.

I'll take a look at those the next time I have assets that I want to copy and include.

@kroko
Copy link
Author

kroko commented Feb 7, 2018

note that fsInlineContents is my made up key name, it can be anything that does not clash with built in keys.

@kroko kroko closed this as completed Mar 15, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants