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

Doesn't find asset paths #4

Closed
AndrewRayCode opened this issue Apr 6, 2015 · 10 comments
Closed

Doesn't find asset paths #4

AndrewRayCode opened this issue Apr 6, 2015 · 10 comments

Comments

@AndrewRayCode
Copy link

webpack.config.js note NOT using a loader with PathRewriterPlugin:

module.exports = {
  entry: {
    index: "./assets/index.html",
  },
  output: {
    path: "public",
    filename: "[name].js",
    publicPath: "/"
  },
  module: {
    loaders: [
      {test: /\.css$/, loader: cssExtractText.extract("style-loader", "css-loader")},
      {test: /\.html$/, loader: PathRewriterPlugin.rewriteAndEmit({
        name: '[name].html'
      })},
    ]
  },
  plugins: [
    cssExtractText,
    new PathRewriterPlugin(),
  ]
};

Folder structure:

assets/
  index.html
  css/
    file.css

Here's index.html:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <link rel="stylesheet" href="[[./css/file.css]]">
  </head>
  <body></body>
</html>

Here's output:

ERROR in assets/index.html: could not resolve path "./css/file.css"

No combination of file paths seems to work.

@skozin
Copy link
Owner

skozin commented Apr 7, 2015

That's because the resulting css file gets created by ExtractTextPlugin during the build. I've tried to explain this in this paragraph, but probably I wasn't clear enough.

For these generated assets, you should specify the target path (relative to the html file), replacing all variable parts of the path with asterisks. If you have no variable parts (no hashing), just provide the path of the resulting css file. For example, if your cssExtractText function places the resulting css to app.css that is located in the same directory as html file, specify href="[[./app.css]]" (path to the resulting asset) instead of href="[[./css/file.css]]" (path to the original asset). If styles get placed to app-[chunkhash].css, then the href will be [[./app-*.css]].

The fact that the html file is an entry point may cause additional issues, or may break the build completely, I haven't tested this. So it's better to require the html file from a JS file instead (see this comment).

@AndrewRayCode
Copy link
Author

Hmmm, we are using this pattern:

<!--[if IE 8]>
  <link rel="stylesheet" href="css/ie8.css">
<![endif]-->
<!--[if IE 9]>
  <link rel="stylesheet" href="css/ie9.css">
<![endif]-->
<!--[if IE 10]>
  <link rel="stylesheet" href="css/ie10.css">
<![endif]-->

Are you saying I'd need to make a new extract text plugin instance for each of those files? I can't reference the built ones by hash because I don't know what the hash would be.

All I really want to achieve is to require static assets from my index file and have the files hashed appropriately. Is that outside the scope of this plugin? I'm a bit new to the webpack dependency graph management nitty gritty, so thank you for the help!

@skozin
Copy link
Owner

skozin commented Apr 7, 2015

All I really want to achieve is to require static assets from my index file and have the files hashed appropriately.

Thiat's exactly the use case this plugin was written for. No, you don't need to know the hash beforehand. For non-generated assets, you don't need to do anything special except for wrapping paths in [[]]. For generated assets, you additionally need to replace all variable hash parts with *, i.e.:

<!--[if IE 8]>
  <link rel="stylesheet" href="[[css/ie8-*.css]]">
<![endif]-->
<!--[if IE 9]>
  <link rel="stylesheet" href="[[css/*/ie9-*.css]]">
<![endif]-->
<!--[if IE 10]>
  <link rel="stylesheet" href="[[css/ie10-*.css]]">
<![endif]-->

E.g. if, after the build, index.html gets placed to _dist/index.html, and ie8.css is a generated asset that gets placed to _dist/css/ie8-xyzabcd.css, the first tag in index.html will be rewritten to <link rel="stylesheet" href="/your/public/path/css/ie8-xyzabcd.css">.

Unfortunately, I have just discovered that, after recent changes to webpack, this plugin stopped working as expected. (I was wrong, everything works except for some bugs with resolving paths when the target of rewriting is located in a subdirectory).

I'll fix this, hopefully during this week, and post a comment here to inform you.

@AndrewRayCode
Copy link
Author

I'm confused - aren't all assets generated by webpack? The built folder that webpack creates is a throw away, it rebuilds it every time. I will never have plain old "ie8.css" hanging out in my built folder.

For ie8-*.css which will be built from source/ie8.css, will I need a new extracttextplugin for each of those individual files, or can I it all with one extracttextplugin? As far as I know you can't do something like new ExtractTextPlugin("[filenamename][chunkhash].css");. If i have to add a new plugin instantiation for any static asset I use in my html, it won't be worth it.

@skozin
Copy link
Owner

skozin commented Apr 7, 2015

When I say "generated" I mean assets that don't exist before the build, like app.js bundle that contains concatenated sources from multiple files. If your ie8-*.css is generated from the single sources/ie8.css file, then you probably need to include no asterisks in the path (but I need to check this as ExtractTextPlugin does some crazy things with internal webpack's assets list).

But, even if ie8-*.css consisted from multiple source files, you would not need to create multiple ExtractTextPlugin instances. If you know that source/ie8.css gets placed to ie8some-unknown-hash.css (and you know that because you have the [filename] part in the ExtractTextPlugin's options), then you'll just need to replace the unknown hash with a (literal) asterisk: [[ie8*.css]]. It will be rewritten to the resulting path. You don't need to specify the actual hash, just an asterisk instead. Or multiple asterisks, if there are multiple variable chunks in the resulting path.

UPD: Sorry for this, probably I need some sleep. You're right, you can't use a single ExtractTextPlugin to emit multiple files. The single instance of ExtractTextPlugin always concatenates all received files to produce a single output file. But webpack-path-rewriter can't help here; it can't create those missing files for you. They just don't exist in the resulting build.

But this is the case only if you want to use css-loader or some other loader that produces JavaScript output (html-loader, maybe some other). When using such loaders, the only way to transform this JavaScript back to normal file contents is to use ExtractTextPlugin. If you need multiple output files, then all you can do is to create multiple ExtractTextPlugin instances. And you'll need to insert asterisks in the path (which in this case needs to be relative to the build root) when using webpack-path-rewriter, because ExtractTextPlugin always breaks relationship between source and resulting files.

All other assets (images, fonts, css/sass/less/stylus without css-loader, etc.) can be handled with the file loader. It emits separate input files to separate output ones. And, when using webpack-path-rewriter, you can refer all these files directly using their original paths, relatively to the file being rewritten.

@skozin
Copy link
Owner

skozin commented Apr 7, 2015

I've just found a bug that prevents resolving assets if an html file is located in a sub-directory (like assets/index.html in your case). I'll try to fix this and other bugs, and publish some examples, as soon as possible.

@skozin
Copy link
Owner

skozin commented Apr 7, 2015

@delvarworld, I've updated my earlier comment. Sorry for the confusion.

@skozin
Copy link
Owner

skozin commented Apr 7, 2015

I've just added another example that builds upon your use-case. However, it doesn't use ExtractTextPlugin and css-loader, so there is no css post-processing. If you need postprocessing and emitting multiple css files, then the only option is to use multiple ExtractTextPlugin instances. I've also updated the plugin to fix re-writing files inside subdirectories.

Does this help?

@AndrewRayCode
Copy link
Author

Phew! Using 1.1.2 I will tentatively say it's working. Thanks for updating the library. I was able to get it to play nicely with the other webpack assets we use with the prefixing strategy:

new ExtractTextPlugin('less-[contenthash].css', {allChunks: true}),
new webpack.optimize.CommonsChunkPlugin({name: "vendor", filename: "vendor-[chunkhash].js"}),

and in my html:

<script type="text/javascript" src="[[vendor-*.js]]"></script>
<script type="text/javascript" src="[[app-*.js]]"></script>

and now it's working for local files:

<link rel="stylesheet" href="[[./css/ie8.css]]">

pretty slick! I think it would be nice if there was a non-jade example in the readme, as well as both local files, entry point files, and webpack built files required in the example.

@skozin
Copy link
Owner

skozin commented Apr 9, 2015

Improving the readme and adding more examples, both basic and advanced ones, is definitely in my plans. Unfortunately, now I'm really busy with a bunch of projects, but I'll try to find time as soon as possible. BTW, you can contribute an example or two ;)

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