I am facing difficulty understanding the nature of URLs/paths and how they are resolved while using the mini-css-extract-plugin
, file-loader
and configuring their options such as the context
and filename
properties.
I am developing a custom theme for WordPress, with the custom theme's folder being where I have initialized the npm project/package.json file and webpack.config.js file. I am using the browser-sync plugin to proxy the local WordPress server to the browser-sync server.
The file-loader is emitting the files into the dist>assets>fonts folder. But the URL being generated in the compiled CSS file is not being resolved correctly.
output CSS, browser console error
GET http://localhost:4444/wp-content/themes/test/dist/css/assets/fonts/my-font.ttf net::ERR_ABORTED 404 (Not Found)
GET http://localhost:4444/wp-content/themes/test/dist/css/assets/fonts/my-font.woff 404 (Not Found)
In the error above the url shows dist/css/assets/fonts/my-font.woff
, which is not what I expected. It was expected to be dist/assets/fonts/my-font.woff
since that is where file-loader emits the files in the dist folder. (as defined in the file-loader context option)
I don't understand why it is adding the css
directory to the fonts url. The only mention of the dist/css
path is in the filename property of the MiniCSSExtractPlugin options. Since that is where i would like the css file to be output.
This can be confirmed by removing the css
path prefix on the filename property. The url then resolves correctly relative to the dist path, but then the compiled css file is placed in the root of the dist folder instead of its own dist/css
sub-directory.
mini css extract plugin options
new MiniCSSExtractPlugin({
filename: 'css/[name].css',
}),
font-face rule in scss file
@font-face {
font-family: 'my-font';
src: url("../assets/fonts/my-font.eot");
src: url("../assets/fonts/my-font.eot") format("embedded-opentype"),
url("../assets/fonts/my-font.ttf") format("truetype"),
url("../assets/fonts/my-font.woff") format("woff"),
url("../assets/fonts/my-font.svg") format("svg");
font-weight: normal;
font-style: normal;
font-display: block;
}
webpack config entry and output
entry: {
'frontend': './src/js/frontend.js',
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: "js/[name].js"
},
module.rules
module: {
rules: [
{...},
{
test: /\.(sa|sc|c)ss$/,
use: [
{
loader: MiniCSSExtractPlugin.loader
},
{
loader: "css-loader"
},
{
loader: "sass-loader"
},
]
},
{
test: /\.(eot|woff|woff2|svg|ttf)([\?]?.*)$/,
use: [
{
loader: 'file-loader',
options: {
context: path.resolve(__dirname, 'src'),
name: '[path][name].[ext]'
}
}
]
}
plugins
plugins: [
new CleanWebpackPlugin(),
new BrowserSyncWebpackPlugin({...}),
new MiniCSSExtractPlugin({
filename: 'css/[name].css',
}),
]
I am a beginner at webpack and I am facing several difficulties trying to get font-face URLs to resolve correctly. I have a feeling that I don't understand the purpose of relative/absolute paths, context and publicpath in the webpack config. How is the URL in the compiled CSS is being determined?