How to change all href and src paths on webpack building? - javascript

I have a websites, written mostly in pug (html preprocessor). I use output.publicPath equal to '/' so I can run webpack in development mode and work easily, treating project folder as a root one, but every href, src and url is an absolute path. I want to change every path by adding some nodes (let's use '/path/to/' for example) in the begging, when I build project. For example, I have an image
img(src="/img/image.jpg")
And after I build this project, I want to receive this:
<img src="/path/to/img/image.jpg">
And to receive the same with hrefs and urls.
I made a webpack build config and setted output.publicPath to '/path/to/' but it changed the pathes of linked css and js files:
mode: "production",
output: {
publicPath: "/HTMLPractice/dist/"
}
I'll be glad to receive any solution, idea or recommendation.

You can set publicPath on the file-loader, so long as the file-loader regex contains the image files.
In your webpack.config.js rules:
{
test: /\.(png|jpe?g|gif)$/i,
loader: 'file-loader',
options: {
publicPath: 'some/path',
},
},
More info: https://webpack.js.org/loaders/file-loader/#publicpath

Related

Why does Webpack 2 output only one of my images?

I'm still fairly new to webpack 2 but I've got most of my configurations working so far. The only thing I'm having some difficulty understanding is that when I run "npm run build" to bundle my files into my "dist" folder I noticed that only 1 of my images are being bundled. I'm using 'file-loader'. FYI all my images still show on my dev-server when I run it and appear under the public paths I assigned. It's only my local output that's not displaying all the images. Anyone know what's going on?
My Folder Structure
webpack.config.js
module.exports = {
mode: "development",
entry: {
app: "app"
},
output: {
path: path.resolve(__dirname, "dist"),
filename: "[name].bundle.js",
publicPath: "/"
},
devServer: {
publicPath: '/',
port: 3000
},
module: {
rules: [
{
test: /\.(png|svg|jpg|gif)$/,
use: [
{
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'images/',
publicPath: 'images/'
}
}
]
}
]
}
}
As you can see in my folder structure, it always builds with only one of my images being outputted. It's not a major issue (I don't think) since all the images still work when I run the app, but I would appreciate it if anyone could help me understand why only one image is outputting to my local 'dist'. Thank you.
Webpack only writes images to disk that you require. This is one of the benefits of Webpack, it only includes assets that your application needs, so Webpack will guarantee those images exist when you deploy.
To add more images to your output, require them either from your Javascript or CSS with url()s
Note that if you're using the dev server, Webpack doesn't write anything to disk, and keeps all compiled assets in memory.

Webpack2 - How to require an image from HTML

Webpack claims to manage module dependencies including image files. I understand that the following webpack config allows me to require jpg files from JS/CSS:
module.exports = {
module: {
rules: [
{
test: /\.jpg$/,
use: [ 'file-loader' ]
}
]
}
}
using url(/image.png) or require('./image.png'), but how would I include an image from an HTML file?
<img src="/image.png">
I know I can use copy-webpack-plugin to copy over static files into the output directory, but I'm wondering if there is a way to require images directly from HTML.
'html-loader' will do this for you by default, however if you are reading this behavior from your main index.html page, you will need to make webpack treat it as module also. Luckily html-webpack-plugin can do this for you in conjunction with html-loader: html-webpack-plugin.

Assets only correctly map up when my application isn't hosted on a pre-existing path

I'm developing an application for use on multiple client sites. These are hosted either as a subdomain or as a path (which I have no control over), like so:
https://application.example.com/#/example-page
https://example.com/application/#/example-page
Here is my Webpack 1 config:
module: {
loaders: [
{
...
},
{
test: /\.(woff2?|eot|svg|ttf|md|jpg|png)$/,
loader: 'file?name=[hash].[ext]'
}
]
},
output: {
path: __dirname + "/dist/build/",
filename: "app.min.js"
}
With this, my assets get compiled into a /build/ folder which also contains the main application JavaScript file:
The issue I'm having is that the compiled assets aren't found if the application is hosted on a pre-existing path (URL example 2 above) but load perfectly fine if no path exists. Doing some debugging reveals that for whatever reason the /build directory must be specified for assets to load on the second URL example, but specifying /build breaks the first URL example:
https://application.example.com/compiled-asset.png &check;
https://example.com/application/compiled-asset.png ⇐ 404
https://application.example.com/build/compiled-asset.png ⇐ 404
https://example.com/application/build/compiled-asset.png &check;
What am I doing wrong here?
Seems the answer to this is to add the publicPath property to the loader itself as following:
loader: 'file-loader?name=[hash].[ext]&publicPath=./build/'
I had previously attempted this with a separate publicPath property, but this didn't achieve anything.

Seems like webpack ignores 'include' and 'exclude' rules

I have following folder setup:
app/
scss/
lib/
grid.css
main.scss
webpack/
webpack.config.js
in my webpack.config.js I have following loaders to handle scss and css:
{
test: /\.(css|scss)$/,
exclude: path.join(__dirname, '..', 'app/scss/lib/'),
loader: ExtractTextPlugin.extract(
'style-loader', 'css-loader?module!resolve-url!postcss-loader!sass-loader?sourceMap'
)
},
{
test: /\.(css|scss)$/,
include: path.join(__dirname, '..', 'app/scss/lib/'),
loader: ExtractTextPlugin.extract('style-loader', 'css-loader')
}
idea here is that css-loader uses modules essentially rewriting a class name like .red to something random like .JHSKJasdasa however, I want it to exclude /lib folder and leave classes that are in it same as they are (vanilla), however still, classes inside grid.css like .container become randomized.
Likely answer is that webpack is getting confused by the path.join - documentation specifies path.resolve. I think it might do a straight string comparison of the paths, so the relative .. is breaking it, therefore the exclusion/inclusion isn't working correctly. path.resolve should resolve to the absolute path.
If that doesn't work, try adding a folder app/scss/src (or similar) to separate out the code you want to use css-loader on. Then include that rather than excludeing lib.

Webpack angularjs copy angularjs templates but don't include in javascript bundle

What I'm trying to do is configure webpack in a way that would copy all the partial html templates that are required in angular 1.x directives etc. into a separate folder (just like the file-loader does for assets referenced from css). I don't want the partial htmls to be included in my javascript bundle but rather have all of them in one folder with hashed names.
I tried configuring the file-loader to do it but when I run webpack in watch mode it also copies the those html in the dist folder again to it appending a new hash and essentially makes an infinite loop as every new html that shows up in that folder is copied, thus a new html appears and again and again. I tried to set an exclude matching pattern for that loader but webpack was still running constantly watching over that folder.
Here is the excerpt of my webpack.config.js file:
module: {
loaders: [
test: /\.html$/,
exclude: /bundle\/templates/,
loader: `file-loader?name=bundle/templates/[name]-[hash].[ext]
]
}
is there a loader that would help me do what I want without resorting to hacks?
Ok I have found the answer. The problem wasn't the file-loader which is configured correctly like this even without the exclude. What caused the infinite loop was a dynamic require that created a regex that matched those copied assets too... So by setting a proper context for this dynamic require the problem was resolved.
In the webpack.config file you can use the same way like this in the loader section.
{
test: /\.html$/,
exclude: path.resolve(__dirname, 'index.html'),
loader: 'file-loader',
options: {
name: '[name].[ext]',
outputPath: 'views/'
}
},
And in the plugins section of the webpack.config file
plugins: [
new HtmlWebpackPlugin({
template: 'index.html',
inject: true
}),
new ExtractTextPlugin('bundle.css')
]
This will copy all the htmls and will be refered from the index.html

Categories

Resources