Closed ghost closed 6 years ago
For the js / css, we are doing:
For images / assets:
I would need your output
options and your image loader config to help you further
@mastilver
Do I read your snippets above correctly to mean that, in manifest.son, the alias should be UN-prefixed with any dir path?
And, as requested (I think I got the relevant pieces ...)
webpack.config.js
const webpack = require('webpack');
const publicPath = "build/";
const commonConfig = merge([
...
output: {
publicPath,
path: PATHS.build,
libraryTarget: 'umd'
},
...
]);
const productionConfig = merge([
...
{
output: {
chunkFilename: 'js/[name].[chunkhash].js',
filename: 'js/[name].[chunkhash].js',
pathinfo: false,
},
},
...
parts.loadImages({
name: "[name].[hash].[ext]"
}),
...
parts.hashNamedModules(),
parts.attachRevision(),
parts.manifest()
]);
webpack.parts.js
...
exports.hashNamedModules = () => ({
plugins: [
new webpack.NamedModulesPlugin()
]
});
exports.manifest = () => ({
plugins: [
new ManifestPlugin({
fileName: ('manifest.json'),
basePath: "",
map: (file) => {
return file;
}
})
]
});
exports.attachRevision = () => ({
plugins: [
new webpack.BannerPlugin({
banner: new GitRevisionPlugin().version(),
}),
],
});
exports.loadImages = ({ include, exclude, name } = {}) => ({
module: {
rules: [
{
test: /\.(gif|png|jpe?g|svg)$/,
include,
exclude,
use: [
{
loader: "file-loader",
options: {
name,
context: "assets",
useRelativePath: true,
hashType: "sha512",
digestType: "hex",
length: 32
}
},
]
}
],
},
});
Alright so you want to remove js/
from output and add it into entry (as the key)
that way it should generate js/test0.js
, ...
removing the js
from output simply lands the targets in
public/build/*{js,map}
rather than as currently, & as intended,
public/build/js/*{js,map}
The issue's not that the actual assets are ending up in the wrong place, it's the confusion around why the manifest is generated DIFFERENTLY for /js/ vs /img/ assets
Oh, sorry I thought you wanted them the same So js/css: name is coming from entry Assets: comes from emitFile: https://github.com/webpack-contrib/file-loader/blob/master/src/index.js#L73
Sorry I really don't know what to do with that.
Starting with
<project>
assets/
img/
test.png
js/
test.js
scss/
test.scss
I want to end up with
<project>
public/
build/
img/
test.<hash>.png
js/
test.<hash>.js
css/
test.<hash>.css
so far so good, that's exactly what I do have.
but I want a consistent manifest path+naming not what I'm currently getting
manifest.json
{
"test.css": "build/js/test.<hash>.css",
"test.css.map": "build/js/test.<hash>.css.map",
"test.js": "build/js/test.<hash>.js",
"test.js.map": "build/js/test.<hash>.js.map",
"img/test.png": "build/img/test.<hash>.png",
}
but this, with consistent alias path/file usage
manifest.json
{
"css/test.css": "build/js/test.<hash>.css",
"css/test.css.map": "build/js/test.<hash>.css.map",
"js/test.js": "build/js/test.<hash>.js",
"js/test.js.map": "build/js/test.<hash>.js.map",
"img/test.png": "build/img/test.<hash>.png",
}
What exactly in my single manifest plugin config do I need to change/add to get there?
Use webpack publicPath option
If you're not interested in helping, just say so.
I can't help you if you don't help me...
What is the manifest you are getting, and what are you expecting?
@mastilver
he (and also myself) has
{
"test.css": "build/js/test.<hash>.css",
"test.css.map": "build/js/test.<hash>.css.map",
"test.js": "build/js/test.<hash>.js",
"test.js.map": "build/js/test.<hash>.js.map",
"img/test.png": "build/img/test.<hash>.png",
}
but we both want:
{
"<publicPath>css/test.css": "<publicPath>js/test.<hash>.css",
"<publicPath>css/test.css.map": "<publicPath>js/test.<hash>.css.map",
"<publicPath>js/test.js": "<publicPath>js/test.<hash>.js",
"<publicPath>js/test.js.map": "<publicPath>js/test.<hash>.js.map",
"<publicPath>img/test.png": "<publicPath>img/test.<hash>.png",
}
My reasoning is that the point of the manifest.json
is to help backend template function resolve logical names into absolute names.
Therefore in dev where there are no hashes, it should resolve to the actual filename, which means often that we have to query with the unhashed filename:
If you consider my publicPath
is static
meaning i would have /static/img/test.png
, then:
MagicalTemplateHelpers.assetUrl = (path) => {
let manifest = {};
try {
const manifest = require(`${MAGICAL_ROOT}/manifest.json`);
} catch (err) {
}
return Object.keys(manifest).includes(path) && manifest[path] || path;
}
<html>
...
<img src="{{ asseturl '/static/img/test.png'}}">
...
</html>
Then in dev it would look like:
<html>
...
<img src="/static/img/test.png">
...
</html>
and in prod it would look like:
<html>
...
<img src="/static/img/test.93845j45.png">
...
</html>
So the reason why I default to the provided path is so that :
Hi @airtonix
As I said earlier, I believe the solution is to add js/
to the keys of your entry
and remove it from output.filename
. Do the same with the filename
options on ExtractTextPlugin
If it doesn't work, give me the manifest, entry
, output
and ExtractTextPlugin
options, before and after you applied this advise
And can you stop using <publicPath>
and <hash>
, it's really confusing...
I am having the same issue. All assets except js
and css
have the correct key in the manifest.json
but the main.css
and main.js
keys are wrong.
Input Files
app.js
css/style.scss
js/script.js
images/...
fonts/...
Ouput Files
dist/manifest.json
dist/js/main.js
dist/css/main.css
dist/fonts/...
dist/images/...
manifest.json
{
"/dist/main.js": "/dist/js/main.62df052c202febdd97aa.js",
"/dist/main.css": "/dist/css/main.8ee4f2b4d0e137b9ef6ee98fb901ab28.css",
"/dist/images/th03.jpg": "/dist/images/th03.3190e504e69661755c3983492c6e66a0.jpg",
"/dist/fonts/roboto-black-webfont.woff2": "/dist/fonts/90f4fdfe1436e82be81f1a1572275375.woff2",
Webpack Config parts
var baseConfig = {
entry: '/app.js',
output: {
filename: PROD ? 'js/[name].[hash].js' : 'js/[name].js',
chunkFilename: PROD ? 'js/[name].[hash].js' : 'js/[name].js',
// Absolute output directory
path: path.resolve(designAssetsOutputFolder + '/dist'),
// Output path from the view of the page
publicPath: '/dist/',
},
module: {
rules: [
{
test: /\.(jpg|jpeg|gif|png)$/,
exclude: /node_modules/,
loader: 'url-loader',
options: {
limit: 10000,
name: PROD ? 'images/[hash].[ext]' : 'images/[name].[ext]'
}
},
{
test: /\.(woff|woff2|eot|ttf|svg)$/,
exclude: /node_modules/,
loader: 'url-loader',
options: {
limit: 10000,
name: PROD ? 'fonts/[hash].[ext]' : 'fonts/[name].[ext]'
}
},
new ExtractTextPlugin({
filename: function (getPath) {
return getPath(PROD ? 'css/[name].[contenthash].css' : 'css/[name].css');
},
allChunks: true
}),
new ManifestPlugin({
basePath: '/dist/',
publicPath: '/dist/',
map: function (file) {
if (PROD) {
// Remove hashes from keys created in CopyWebpackPlugin which does not correctly support manifest files
file.name = file.name.replace(/(\.[a-f0-9]{32})(\..*)$/, '$2');
}
return file;
}
})
Changing the entry
to /js/app.js
and removing js
from output.filename
does not work as that file is not in the js folder. It also would not work as the css files are still wrong.
Doing the above and moving the app.js
into /js/app.js
will still result in an incorrect manifest file:
manifest.json
{
"/dist/main.js": "/dist/main.21e3024ef4194d6c65b7.js",
"/dist/main.css": "/dist/css/main.8ee4f2b4d0e137b9ef6ee98fb901ab28.css",
"/dist/images/th03.jpg": "/dist/images/th03.3190e504e69661755c3983492c6e66a0.jpg",
"/dist/fonts/roboto-black-webfont.woff2": "/dist/fonts/90f4fdfe1436e82be81f1a1572275375.woff2",
I need my manifest to look like this:
manifest.json
{
"/dist/js/main.js": "/dist/js/main.62df052c202febdd97aa.js",
"/dist/css/main.css": "/dist/css/main.8ee4f2b4d0e137b9ef6ee98fb901ab28.css",
"/dist/images/th03.jpg": "/dist/images/th03.3190e504e69661755c3983492c6e66a0.jpg",
"/dist/fonts/roboto-black-webfont.woff2": "/dist/fonts/90f4fdfe1436e82be81f1a1572275375.woff2",
I am using "webpack-manifest-plugin": "^2.0.4"
To get it work you can do the following hack:
new ManifestPlugin({
map: function (file) {
if (file.name.match(/main\.css/g)) {
file.name = file.name.replace(/(main\.css)/, 'css/$1');
}
if (file.name.match(/main\.js/g)) {
file.name = file.name.replace(/(main\.js)/, 'js/$1');
}
return file;
}
})
My project's assets are arranged as
I hash files, and have set up manifest generation
My fileloader's gather/process all, and output as
the generated manifest contains
Notice that ONLY the png image file's manifest alias has the prefixed "img/" path; the .js/.css entries do not.
(1) Should manifest aliases consistently have the full relative path preceding the alias, or not?
(2) What in my single manifest config is the cause of the difference in behavior prefixing behavior? Is there additional config needed in the manifest plugin's config -- or other module?