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

publicPath can now be a function #373

Merged
merged 7 commits into from Apr 8, 2019

Conversation

karlvr
Copy link
Contributor

@karlvr karlvr commented Apr 4, 2019

Also added schema validation for publicPath.

This PR contains a:

  • bugfix
  • new feature
  • code refactor
  • test update
  • typo fix
  • metadata update

Motivation / Use-Case

Addresses #367 by allowing publicPath to be a function, therefore allowing the publicPath to be adjusted according to the resource.

Rationale

The browser treats URLs in CSS files relative to the CSS file, so having URLs be relative to the CSS file is natural in CSS. A common solution is to set publicPath to an absolute path, but that isn't always possible. Another common solution is to set publicPath to ../, which assumes that your CSS file is output into ./css/ (or some other folder, but just one folder) and fails if you output a CSS file more than one folder deep.

(URLs in the CSS that comes into mini-css-extract-plugin are made relative to the context by css-loader, which produces JavaScript where URLs should be relative to the context)

The example in the README demonstrates a publicPath function that solves the relative path problem above, and is an alternative approach to #368

Additional contents

I also added schema validation for publicPath, which seemed like a useful addition now that it's a bit more complicated. Previously the loader would simply ignore publicPath if it was anything other than a string.

Also added schema validation for publicPath.
@karlvr
Copy link
Contributor Author

karlvr commented Apr 4, 2019

@evilebottnawi One thing about this; I tried to follow the pattern of file-loader for the publicPath function, except I didn't have the url parameter as we don't appear to have that. However of course mini-css-extract-plugin does know where the output file is going as it writes it itself in the plugin side. Is that not correct? So we could provide the eventual output path of the file?

If that's the case then we can do this perfectly and emit relative URLs in our output file that will work. Contrary to my previous PR #368 which made paths relative to the source file (which probably worked).

Given that the example on the README of mini-css-extract-plugin is publicPath: '../', which doesn't work if the CSS file is output anywhere other than one-level deep in the folder hierarchy, wouldn't it be better to add an option to make publicPath better by default like #368 could offer?

Copy link
Member

@alexander-akait alexander-akait left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, need add tests and we can merge 👍

const loaders = this.loaders.slice(this.loaderIndex + 1);
this.addDependency(this.resourcePath);
const childFilename = '*'; // eslint-disable-line no-path-concat
const publicPath =
typeof query.publicPath === 'string'
? query.publicPath
: typeof query.publicPath === 'function'
? query.publicPath(this.resourcePath, this.rootContext)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need here url as in file-loader because file-loader for other purpose (answer on above question)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@evilebottnawi in file-loader it's because file-loader can choose to output the file itself? Doesn't the plugin do exactly that?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@karlvr @evilebottnawi Just wanted to let you know that this introduces a breaking change in the case when the publicPath is set to an empty string meaning that resources are located in the same directory as the css file, e.g. dist/app.css, dist/aResource.png. With the introduced change the publicPath is transformed to a / and so the resource path becomes /aResource.png which is clearly not desired.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@evilebottnawi @rmja

That change was to follow the same behaviour in https://github.com/webpack-contrib/file-loader/blob/master/src/index.js#L37

I'm really sorry about this regression! @evilebottnawi shall we introduce a special case for an empty string here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@karlvr I have created #384

@karlvr
Copy link
Contributor Author

karlvr commented Apr 5, 2019

@evilebottnawi test added!

Copy link
Member

@alexander-akait alexander-akait left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good PR! Need resolve logic for /. We don't change this for function because you can configure webserver handle path/to and path/to/ in difference way, it is doesn't standard and not a best practice, so we fix it only for string due in 99% it is mistake

Copy link
Member

@alexander-akait alexander-akait left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And let's make two tests with / and without and we can merge 👍

Make it consistent with new publicpath-trailing-slash test
In order to test output into nested directories, such as I’m about to add for the publicpath-function test.
With output of the CSS into a nested folder the computation of the relative publicPath makes sense.
@karlvr
Copy link
Contributor Author

karlvr commented Apr 5, 2019

@evilebottnawi please excuse the force pushes! I've been trying to make the publicpath-function test match what I've been trying to do, and I've realised what was missing from my previous description of the issue.

The test previously used index.js to import the CSS file, and therefore didn't care where it ended up. In my example I have the CSS file as an entry point, and I care where it ends up (semantically, and I might reference the file from outside of the build chain).

With my publicPath function (used in the test and in the README) it assumes that the nesting of the entry point output is the same as the entry point input, which it is in my example.

It's such a shame that I don't appear to be able to determine the entry point output in the loader to compute a relative publicPath with impunity! Anyway, I'm going to add one more file to the publicpath-function test to demonstrate another CSS file at a different nesting, to hopefully lead anyone who would like to achieve this.

Added a second entry point / output at different nesting demonstrating the application of the publicPath function
@alexander-akait
Copy link
Member

Anyway we can add more arguments to publicPath in future

@karlvr
Copy link
Contributor Author

karlvr commented Apr 5, 2019

@evilebottnawi the simple-publicpath test is an existing test that has a trailing slash on the publicPath, so we now have a test with and without.

I have finished, unless there's anything else you'd like to suggest. I hope you don't mind the addition of recursive checking out expected output to the tests. In porting legacy projects into webpack it has been important to maintain an existing output file structure (rather than not needing to care where the generated files end up), hence the multiple entry points and caring about nested folders!

@karlvr
Copy link
Contributor Author

karlvr commented Apr 5, 2019

@evilebottnawi agreed we can add more arguments, but we can't reorder them without breaking stuff. Any other arguments you think we should / could add at this stage that want to not go on the end?

@alexander-akait
Copy link
Member

@ericclemmons yep, it is hard to imagine what developers need, so we will add their by request, for release 1.0.0 we normalize their order, it is not scary. When you have big package with a lot of developers major release are inevitable

@karlvr
Copy link
Contributor Author

karlvr commented Apr 5, 2019

@evilebottnawi thanks for this collaboration, it's been a pleasure.

@alexander-akait
Copy link
Member

It is very strange what CI broken 😞 Locally works fine?

@karlvr
Copy link
Contributor Author

karlvr commented Apr 5, 2019

@evilebottnawi looks like it's an audit issue?

1 vulnerability requires manual review. See the full report for details.

from https://circleci.com/gh/webpack-contrib/mini-css-extract-plugin/1038

┌──────────────────────────────────────────────────────────────────────────────┐
│                                Manual Review                                 │
│            Some vulnerabilities require your attention to resolve            │
│                                                                              │
│         Visit https://go.npm.me/audit-guide for additional guidance          │
└──────────────────────────────────────────────────────────────────────────────┘
┌───────────────┬──────────────────────────────────────────────────────────────┐
│ Low           │ Regular Expression Denial of Service                         │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Package       │ braces                                                       │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Patched in    │ >=2.3.1                                                      │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Dependency of │ babel-cli [dev]                                              │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ Path          │ babel-cli > chokidar > anymatch > micromatch > braces        │
├───────────────┼──────────────────────────────────────────────────────────────┤
│ More info     │ https://npmjs.com/advisories/786                             │
└───────────────┴──────────────────────────────────────────────────────────────┘

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

Successfully merging this pull request may close these issues.

None yet

3 participants