-
-
Notifications
You must be signed in to change notification settings - Fork 256
feat(index): add cssOutputPath
option (option.cssOutputPath
)
#150
Conversation
.gitignore
Outdated
!.gitignore | ||
!.travis.yml |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why to change these two?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep these will be taken care of by #130
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I ignored all dotfiles in my last commit, but I forgot to allow .travis.yml too, not only the .gitignore.
About the .editorconfig it was my carelessness shouldn't be there yet (what to led change formatting), I've been working on another machine and it would configure wrong. Sorry!
index.js
Outdated
@@ -1,80 +1,106 @@ | |||
/* | |||
MIT License http://www.opensource.org/licenses/mit-license.php | |||
Author Tobias Koppers @sokra | |||
MIT License http://www.opensource.org/licenses/mit-license.php |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The formatting change should probably be a separate PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
npm i -D jsdoc-to-markdown
package.json
{
"scripts": {
"docs": "jsdoc2md index.js > LOADER.md"
}
}
index.js
var path = require('path')
...
/**
* File Loader
*
* > Loads and emits files
*
* @author Tobias Koppers (@sokra)
* @version 0.12.0
* @license MIT
*
* @module file-loader
*
* @requires path
* @requires loaderUtils
*
* @method loader
*
* @param {String} file File
*
* @return {String} module Module (File)
*/
module.exports = function (file) {...}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bebraw I agree. I'll change this.
@michael-ciniawsky I don't know if I can change the header. I see a pattern in other plugins also can't occur a conflict with #130 later?
.gitignore
Outdated
!.gitignore | ||
!.travis.yml |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep these will be taken care of by #130
index.js
Outdated
@@ -1,80 +1,106 @@ | |||
/* | |||
MIT License http://www.opensource.org/licenses/mit-license.php | |||
Author Tobias Koppers @sokra | |||
MIT License http://www.opensource.org/licenses/mit-license.php |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
npm i -D jsdoc-to-markdown
package.json
{
"scripts": {
"docs": "jsdoc2md index.js > LOADER.md"
}
}
index.js
var path = require('path')
...
/**
* File Loader
*
* > Loads and emits files
*
* @author Tobias Koppers (@sokra)
* @version 0.12.0
* @license MIT
*
* @module file-loader
*
* @requires path
* @requires loaderUtils
*
* @method loader
*
* @param {String} file File
*
* @return {String} module Module (File)
*/
module.exports = function (file) {...}
index.js
Outdated
}; | ||
var query = loaderUtils.getOptions(this) || {}; | ||
var configKey = query.config || "fileLoader"; | ||
var options = this.options[configKey] || {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
General Question: Is this still needed 😛 ? What does this.options
contain ? 🙃 (webpack.config.js
) ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That was already there and I preferred to keep it as it was to avoid breaks.
About the question, yes! this.options is from webpack.config.js
🙃
index.js
Outdated
var query = loaderUtils.getOptions(this) || {}; | ||
var configKey = query.config || "fileLoader"; | ||
var options = this.options[configKey] || {}; | ||
var config = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
config
=> defaults
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeap! But textOutputPath
I kept as undefined then I don't think to be necessary there, just as the regExp
option isn't. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
? 🙃
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sry I didn't understand before, I thought it was part of the review ^^
index.js
Outdated
config[attr] = options[attr]; | ||
}); | ||
// options takes precedence over config | ||
Object.keys(options).forEach(function(attr) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Object.assign
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That was there already, I believe it's to support older versions of node.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
kk sry leave it :) I will test it when time and it's separate PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Stick a todo in there to switch this to Object.assign
in the defaults pull request which removes support for older node version.
index.js
Outdated
config[attr] = query[attr]; | ||
}); | ||
// query takes precedence over config and options | ||
Object.keys(query).forEach(function(attr) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Object.assign
? Why is that done twice ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That was there already too, all these changes is polluted by whitespace simply add ?w=1
at the end of the URI.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
kk
index.js
Outdated
); | ||
} | ||
// We have access only to entry point relationships. So we work with this relations. | ||
var issuerContext = (this._module && this._module.issuer && this._module.issuer.context) || context; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const issuer = {...}
const relative = { url: '...' , path: '...' }
const output = {...}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm sorry, I didn't understand these review.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const issuer = {}
const output = this.options.output || {}
const relative = {}
issuer.context = (this._module && this._module.issuer && this._module.issuer.context) || context;
relative.url = issuer.ctx && path.relative(issuer.context, this.resourcePath);
relative.path = relative.url && path.dirname(relativeUrl);
output.dirname = relative.path
.replace(/\.\.(\/|\\)/g, "")
.split(path.sep)
.join("/");
if (output.dirname.indexOf(outputPath) !== 0) output.dirname = outputPath;
outputPath = path.join(output.dirname, url)
.split(path.sep)
.join("/");
if (output.filename && output.filename !== "extract-text-webpack-plugin-output-filename") {
relative.path = output.dirname;
} else if (toString.call(config.textOutputPath) === "[object String]") {
output.context = output.path.replace(this.options.context + path.sep, "");
output.asset = path.join(context, output.context, output.dirname);
issuer.output = path.join(context, output.context, config.textOutputPath);
relative.path = path.relative(issuer.output, output.asset);
}
url = path
.join(relative.path, url)
.split(path.sep)
.join("/");
} else if (config.outputPath) {
url = outputPath;
} else {
outputPath = url;
}
It about grouping the various values/variables together 😛
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It makes sense for me, but I also think it's necessary another PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why ? 🙃
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nope not really 😛 , but it's ok to leave it for now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@michael-ciniawsky So, let's do it! 🙃
EDIT
Something like this?
https://gist.github.com/adriancmiranda/43478d0ad1b8402b412d5c56ef3dd57f
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the gist a newline \n
after the follwing lines and I'm 👍 on Code Style 😛 L50, 65, 74, 84
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
up-to-date
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@adriancmiranda Update this PR with the Gist, we will squash it later anyways
index.js
Outdated
if (output.filename && output.filename !== "extract-text-webpack-plugin-output-filename") { | ||
relativePath = outputDirname; | ||
} else if (toString.call(config.textOutputPath) === "[object String]") { | ||
var outputPackageDirname = output.path.replace(this.options.context + path.sep, ""); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See the comment directly above, please group issuer, relative, output
via an {Object}
Is this in general 'only' related/compatible to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
extract-text-webpack-plugin-output-filename
is sent for all requested files (except js entries) by the specific plugin, but the output.filename is from webpack.config
then I don't think that's a problem to use with another plugin unless it also sends something like another-plugin-output-filename
for all requested files.
The textOutputPath
is relative to the extracted file (e.g css), is from the issuer, not for your assets. I'm not sure if the extract-text(for example) is used only for CSS files so I prefer to keep the generic name or maybe cssOutputPath
. I don't know. What do you think?
.gitignore
Outdated
!.gitignore | ||
!.travis.yml |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I ignored all dotfiles in my last commit, but I forgot to allow .travis.yml too, not only the .gitignore.
About the .editorconfig it was my carelessness shouldn't be there yet (what to led change formatting), I've been working on another machine and it would configure wrong. Sorry!
index.js
Outdated
}; | ||
var query = loaderUtils.getOptions(this) || {}; | ||
var configKey = query.config || "fileLoader"; | ||
var options = this.options[configKey] || {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That was already there and I preferred to keep it as it was to avoid breaks.
About the question, yes! this.options is from webpack.config.js
🙃
index.js
Outdated
var query = loaderUtils.getOptions(this) || {}; | ||
var configKey = query.config || "fileLoader"; | ||
var options = this.options[configKey] || {}; | ||
var config = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeap! But textOutputPath
I kept as undefined then I don't think to be necessary there, just as the regExp
option isn't. What do you think?
index.js
Outdated
config[attr] = options[attr]; | ||
}); | ||
// options takes precedence over config | ||
Object.keys(options).forEach(function(attr) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That was there already, I believe it's to support older versions of node.
index.js
Outdated
config[attr] = query[attr]; | ||
}); | ||
// query takes precedence over config and options | ||
Object.keys(query).forEach(function(attr) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That was there already too, all these changes is polluted by whitespace simply add ?w=1
at the end of the URI.
index.js
Outdated
); | ||
} | ||
// We have access only to entry point relationships. So we work with this relations. | ||
var issuerContext = (this._module && this._module.issuer && this._module.issuer.context) || context; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm sorry, I didn't understand these review.
kk, yeah this might be out-of-scope of this PR, I'm sry to bikeshed about this, but we need to make sure to not let any specific hooks relying on other plugins/loaders into loaders/plugins in general when possible and try go for the generic solution first. So if we can design it as a generic hook for plugins in need of the same functionality as ETWP, we should do it. But this doesn't mean it's a blocker for this PR :), tbh I have no clue if any other plugin would need this aswell. I just need to clearify this 😛
If we go with this, we need to make sure folks using the
|
@michael-ciniawsky No, you're totally right and I'm happy to answer. EDIT |
index.js
Outdated
var output = this.options.output || {}; | ||
if (output.filename && output.filename !== "extract-text-webpack-plugin-output-filename") { | ||
if (output.filename && path.extname(output.filename) === ".js") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's wrong yet. I remembered, it has 'jsx' too, maybe another kind of file for scripts. Maybe we need only to know if the file has an extension.
@adriancmiranda - - I have set this to blocked ( #165 ) & moved this feature into |
@d3viant0ne Thank you... and I'm sorry for the noise 😉 |
Codecov Report
@@ Coverage Diff @@
## master #150 +/- ##
==========================================
+ Coverage 97.14% 97.87% +0.72%
==========================================
Files 2 3 +1
Lines 35 47 +12
Branches 16 20 +4
==========================================
+ Hits 34 46 +12
Misses 1 1
Continue to review full report at Codecov.
|
@adriancmiranda @michael-ciniawsky @d3viant0ne What about this solution? Will it ever be merged? Half of my images end up in the parent folder. Also with all politeness (and seriousness) I think the priority is a lot higher than "nice to have". Thanks for considering! |
Hey @stereokai I'm waiting for another review yet. 😉
|
@adriancmiranda Actually, here's an update: After 2 days of trial and error (Thanks Webpack docs!) I found out that there's a way to control file-loader's output and replicate the file structure of the source directory in the output directory. It's the Webpack setting
Here's an example of how to use it. Let's say your desired result is to load an image via Your project's file structure is:
And the desired result is:
The configuration for this is:
And that is because you want to replicate the file structure under If you wanted to remove the
|
@stereokai How about the links? |
@adriancmiranda what do you mean? I was getting build assets in parent folders of the project root. Are we not talking about the same problem? |
@stereokai What I'm proposing isn't exactly solving a problem from file-loader (file-loader is fine), but provide an additional solution to, so that you can also have relative paths in the compiled version of your code. Your example works perfectly, however, it only has one file-per-configuration context. So let's say you have this structure: src/
│ └── scripts/index.js -> require('../assets/images/placehold.jpg')
│ └── assets/
│ └── images/ you get something like this, right?
My proposal is that you have a result like this:
considering of course that you'll replicate build/
│ └── index.js -> require('./assets/images/placehold.jpg')
│ └── assets/
│ └── images/ In this case you should have this path
instead
P.S: Here is some tests extracted from here to you play with this. |
@adriancmiranda Does this line: |
@stereokai Yes, it is, sorry about it. I wasn't clear |
@adriancmiranda I'm sorry but I don't understand what it is you are trying to achieve |
@stereokai If you are curious about this, I recommend to you test this version. I would like to hear your feedback 😉 |
The solution worked on my project (Cordova project so I cannot use In my package.json I put: "file-loader": "git://github.com/woshi82/file-loader.git#master" In my webpack config: modules: {
rules: [
// ...
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 5000,
name: utils.assetsPath('img/[name].[hash:7].[ext]'),
useRelativePath: process.env.NODE_ENV === "production",
cssOutputPath: 'static/css'
}
}
]
} The piece of CSS I am using: select {
background: url('../assets/select-arrow.png') no-repeat right transparent;
} The generated CSS rule: select {
background: url(../../assets/static/img/select-arrow.8493640.png) no-repeat 100% transparent;
} |
@Leward The |
option.cssOutputPath
cssOutputPath
option (option.cssOutputPath
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should add any type specific (css
) options to this loader and the orginial problem definitely lied in extract-text-webpack-plugin
, which shouldn't affect a simple loader like the file-loader
I'm going to close this PR for now, but feel free to reopen if in disagreement and to reiterate
What kind of change does this PR introduce?
A bugfix and a feature (
cssOutputPath
)Did you add tests for your changes?
no
If relevant, did you update the README?
The readme file has been updated
Summary
#149 and #135 public path validation
Does this PR introduce a breaking change?
no
Other information
Entry files and CSS output path doesn't pass through the
file-loader
so we haven't access to the file's context to compare with your issuer context correctly then we need to kidnap javascript entries and manually pass the CSS file output path using a new property (i.e.cssOutputPath
). This should prevent unexpected output paths.