Closed MiniGod closed 4 years ago
Your configuration provide expected output, i can't understand why you expected other behavior and say what it is bug :confused: Describe your use case and why you need this logic.
Thanks for the fast response!
I was trying to configure the outputPath
for the files that ace-builds/webpack-resolver
pulls in. They all end up in the root of dist/
which I did not want.
See: https://github.com/ajaxorg/ace-builds/blob/master/webpack-resolver.js
I might very well be doing this the wrong way.
@MiniGod hm, can you provide full reproducible repo to investigate problem?
You expected what ace.config.setModuleUrl("ace/ext/beautify", require("file-loader!./b.js"));
=> ace.config.setModuleUrl("ace/ext/beautify", ace.define(/* foo bar */));
, right?
Input:
ace.config.setModuleUrl("ace/ext/beautify", require("file-loader!./b.js"));`
Output:
ace.config.setModuleUrl("ace/ext/beautify", __webpack_public_path__ + "lib/7e18d1cdb1e87c1556053fa0b9bf7a98.js");
right?
Yes that's the output that I'd expect. However, the output in dist is like this:
ace.config.setModuleUrl("ace/ext/beautify", __webpack_public_path__ + "9fd622c116f2bb83d54eae2c49d8141e.js");
And the content of dist/9fd622c116f2bb83d54eae2c49d8141e.js
is:
module.exports = __webpack_public_path__ + "lib/f588e2144d0ba4ab157205ce359e6a0a.js";
So ace tries to load that file as the js file defining said module, which errors with something along the lines of "module is not defined".
If you still want me to create a full reproducible repo, let me know.
Just for information, what is use case, why you need put files in lib?
The goal is that the public path to the files from ace will be something like: https://hostname/admin/lib/ace/f588e2144d0ba4ab157205ce359e6a0a.js
Webpack builds an SPA and I have the public path set to /admin/
. Since ace spits out 400 files I don't want those directly inside of the admin folder.
:+1: thanks, i will look on it in near future
Same issue happens for importing images(SVG as far as I tested). If the returned public path is used in HTML attributes like src
. the browser will fetch the string like module.exports = __webpack_public_path__ ...
and fail to display the image.
This also happens when rules of loaders testing over a same file(e.g. an svg can be an image or a font, and hence may be included in separate rules with different name
or outputPath
options. This is the case I encountered).
I think this is due to the emitFile
interface of webpack instead of file-loader. Such behaviour is reasonable for avoiding same dependencies with duplicate js sources, but not for static assets. Since I am still not very familiar with webpack, please let me know if there are more appropriate approaches for my use case(I think matching rules on different path is enough currently?)
Here interesting case:
file-loader
in a configuration you need to use require("!!file-loader!./b.js")
/import("!!file-loader!./b.js")
, it is disable loader from configuration ( or just remove file-loader
) from a request.@austin880625 I don't know what do you want to achieve but if you create a reproducible test repo with simple readme I will help you, thanks
@evilebottnawi I made the repository here. I currently consider this as a configuration problem. But I am still confused about how does webpack use loaders to generate the bundles, so below might not really relate to this problem but I will appreciate it if there is an answer.
I know that a loader is a functions that returns a JS module by definition. But I thought webpack will make the bundled js contain these output modules at the end. So there are two possibilities about what these modules do:
The module exports content of processed files in formats that can be contained in JS like string, object, or function. For example, a CSS loader may return something like export default "h1{color:red;}"
and HTML loader can transform <link href="./style.css">
into JS code that inserts <style>h1{color:red;}</style>
The module just exports the public path of the processed file and emits(maybe copy but as you said that's not what this module does) the file into the output path. In previous example, the CSS loader return things like export default "/dist/css/style.css"
and the link
tag will be transformed into <link href="/dist/css/style.css">
, or the HTML loader will try to load the content of /dist/css/style.css
and then insert it into <style>
tag
Because of the existences of name
, outputPath
and publicPath
options in most loaders, the second case makes more sense. However in CSS example, the content of /dist/css/style.css
can never be module.exports = __webpack_public_path__ + "css/style.css"
but h1{color:red;}
, and this happens in SVG files in the given repository. So should the loaders always be aware that the content inside the public path may not be the actual processed file content? or does it simply mean that the same file cannot be passed to a same loader(by either require
in this original issue or being covered by different config rules with different name
or outputPath
options)?
@austin880625 Sorry for delay, if you need content of SVG file you need to use raw-loader
instead file-loader
, file-loader
emit file and return URL to an asset, I see what you want to achieve - get source of the asset and URL to asset, but it is bad idea, in this case you will get big bundle, because we should keep the source of the asset in bundle (as string) and emit the asset with the same source on disk (so you will have the source of the asset twice - first on disk, second in bundle). If you still want it, you can write own loader using pitch
phase and reexport source of the asset.
For original issue you need to use require("!file-loader!./b.js")
(!
disable normal loaders) because you pass file twice to file-loader
Expected Behavior
The
module.exports
generated for therequire
should always be the path to the file with the content, not a file that exports the path to said file.Actual Behavior
When a file is loaded with
require('file-loader!./b.js')
, as well as configured inwebpack.config.js
, two files are being emitted fromfile-loader
. This results in using the wrong file path to the content.The files:
dist/9fd622c116f2bb83d54eae2c49d8141e.js
A file thatmodule.exports
the filename of the 2nd file.dist/lib/f588e2144d0ba4ab157205ce359e6a0a.js
The actual file.File tree:
The
module.exports
generated for therequire
(insidedist/main.js
) is the path to the 1st file. This is not the file with the content. Content ofdist/9fd622c116f2bb83d54eae2c49d8141e.js
:Code
How Do We Reproduce?
https://gist.github.com/MiniGod/2e4615fe2ca6762513a8acd50a59bad7
Notice
a.js
is doingrequire("file-loader!./b.js")
, andfile-loader
is also configured inwebpack.config.js
forb.js
in an attempt to customize theoutputPath
forb.js
.Background
I was trying to use
ace-builds
, and specificallyace-builds/webpack-resolver
, and configure the output path. I've since gone with a different approach, but this still seems like a bug.