Absolute paths in pug template results in "Module not found" in webpack-dev-server

145 views Asked by At

After I upgraded from html-loader 1.1 to html-loader 4.2 the absolute paths in my pug files gives me the following error:

Module not found: Error: Can't resolve '/js/app.bundle.2.1.8.js' in '/Users/username/reponame/src/resources/views'

I have the following configs:

package.json

"html-loader": "^4.2.0",
"html-webpack-plugin": "^5.5.1",
"pug-html-loader": "^1.1.5",
"webpack": "^5.83.1",
"webpack-cli": "^5.1.1",
"webpack-dev-server": "^4.15.0",
"webpack-merge": "^5.9.0",
"webpack-node-externals": "^3.0.0",
"webpackbar": "^5.0.2"

index.pug

doctype html
html(lang="no")
    head
        meta(charset="utf-8")
        meta(name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, viewport-fit=cover")
        link(rel="shortcut icon" type="image/x-icon" href="data:image/x-icon;,")
        link(rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,400i,500,500i,700,700i&display=swap")
        link(rel="stylesheet" href="/css/app.bundle.2.1.8.css")
        title APP NAME
    body
        #app
  
        script(src="/js/app.bundle.2.1.8.js")

webpack.config.js

const dotenv = require("dotenv")
const path = require("path")
const webpack = require("webpack")
const appPackage = require("./package.json")
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
const SpriteLoaderPlugin = require("svg-sprite-loader/plugin")
const HtmlWebPackPlugin = require("html-webpack-plugin")
const WebpackBar = require("webpackbar")
const express = require("express")

module.exports = (_env, _argv) => {
const env = {
    ...dotenv.config().parsed,
    ...process.env,
    NODE_ENV: process.env.NODE_ENV ?? "development",
}

const isLocalOrDevelopment = ["local", "development"].includes(env.NODE_ENV)
const isProduction = !isLocalOrDevelopment
const environment = env.ENVIRONMENT


let platformEnv = 2
switch (env.APP_ENV) {
    case "development":
        platformEnv = 1
        break
    case "production":
        platformEnv = 3
        break
    default: // preprod, local etc.
        platformEnv = 2
        break
}

return {
    devtool: isLocalOrDevelopment && "eval-source-map",
    mode: isLocalOrDevelopment ? "development" : "production",
    entry: {
        app: ["./src/index.tsx"],
    },
    output: {
        path: path.resolve(__dirname, "dist/public"),
        filename: `js/[name].bundle.${appPackage.version}.js`,
        chunkFilename: `js/[name].bundle.${appPackage.version}.js`,
        publicPath: "/",
    },
    optimization: {
        runtimeChunk: false,
    },
    plugins: [
        new webpack.ProvidePlugin({
            process: "process/browser",
        }),
        new SpriteLoaderPlugin({ plainSprite: true }),
        new WebpackBar(),
        ...(isLocalOrDevelopment
            ? [
                  new HtmlWebPackPlugin({
                      template: "./src/resources/views/index.pug",
                      filename: "./index.html",
                      inject: false,
                  }),
                  new HtmlWebPackPlugin({
                      template: "./src/resources/views/error.pug",
                      filename: "./error.html",
                      inject: false,
                  }),
                  new webpack.DefinePlugin(envKeys),
              ]
            : [
                  new MiniCssExtractPlugin({
                      filename: `./css/[name].bundle.${appPackage.version}.css`,
                      chunkFilename: `./css/[name].bundle.${appPackage.version}.css`,
                  }),
              ]),
    ],
    module: {
        rules: [
            {
                test: /\.(eot|woff|woff2)$/,
                type: "asset/resource",
                generator: {
                    filename: "[name].[ext]",
                    outputPath: "fonts/",
                    publicPath: "fonts/",
                },
            },
            {
                test: /\.(jpg|jpeg|png|webp)$/,
                type: "asset/resource",
                generator: {
                    filename: "[name].[ext]",
                    outputPath: "images/",
                    publicPath: "images/",
                },
            },
            {
                test: /\.svg$/,
                use: [
                    {
                        loader: "svg-sprite-loader",
                        options: {
                            extract: true,
                            spriteFilename: `gfx/iconset.${appPackage.version}.svg`,
                        },
                    },
                    "svgo-loader",
                ],
            },
            {
                test: /\.(js|jsx|ts|tsx)$/,
                loader: require.resolve("babel-loader"),
                options: {
                    cacheDirectory: true,
                },
            },
            {
                test: /\.(scss|css)$/,
                exclude: /\.m\.s?css$/,
                use: [
                    ...(isProduction ? [MiniCssExtractPlugin.loader] : [require.resolve("style-loader")]),
                    {
                        loader: "css-loader",
                        options: {
                            importLoaders: 3, // IMPORTANT! CHANGE ACCORDING TO NUMBER OF OTHER STYLE LOADERS
                            url: false,
                            modules: "icss",
                        },
                    },
                    "postcss-loader",
                    "sass-loader",
                    {
                        loader: "sass-resources-loader",
                        options: {
                            resources: [
                                path.resolve(__dirname, "src/styles/abstracts/variables.m.scss"),
                                path.resolve(__dirname, "src/styles/abstracts/mixins.scss"),
                            ],
                        },
                    },
                ],
            },
            {
                test: /\.m\.s?css$/,
                use: [
                    ...(isProduction ? [MiniCssExtractPlugin.loader] : [require.resolve("style-loader")]),
                    {
                        loader: "css-loader",
                        options: {
                            importLoaders: 3, // IMPORTANT! CHANGE ACCORDING TO NUMBER OF OTHER STYLE LOADERS
                            url: false,
                            modules: {
                                localIdentName: "[name]__[local]__[hash:base64:5]",
                            },
                        },
                    },
                    "postcss-loader",
                    "sass-loader",
                    {
                        loader: "sass-resources-loader",
                        options: {
                            resources: [
                                path.resolve(__dirname, "src/styles/abstracts/variables.m.scss"),
                                path.resolve(__dirname, "src/styles/abstracts/mixins.scss"),
                            ],
                        },
                    },
                ],
            },
            ...(isLocalOrDevelopment
                ? [
                      {
                          test: /\.pug$/,
                          use: [
                              {
                                  loader: "html-loader",
                                  options: {
                                      esModule: false,
                                  },
                              },
                              {
                                  loader: "pug-html-loader",
                                  options: {
                                      basedir: path.resolve(__dirname, "dist/public"),
                                  },
                              },
                          ],
                      },
                  ]
                : []),
        ],
    },
    resolve: {
        extensions: [".js", ".jsx", ".ts", ".tsx"],
        alias: {
   
            "@pages": path.resolve(__dirname, "src/pages/"),
            "@components": path.resolve(__dirname, "src/components/"),
            "@resources": path.resolve(__dirname, "src/resources/"),
            "@utils": path.resolve(__dirname, "src/utils/"),
            "@store": path.resolve(__dirname, "src/store/"),
            "@styles": path.resolve(__dirname, "src/styles/"),
        },
    },
    stats: {
        hash: false,
        version: false,
        timings: false,
        children: false,
        errors: true,
    },
    devServer: {
        headers: { "Service-Worker-Allowed": "/" },
        liveReload: false,
        host: "localhost",
        port: env.PORT || 3030,
        allowedHosts: "all",
        compress: true,
        static: {
            directory: path.resolve(__dirname, "dist/public"),
            publicPath: "/",
        },
        setupMiddlewares: (middlewares, devServer) => {
            devServer.app.use("/", express.static(path.resolve(__dirname, "dist/public")))
            return middlewares
        },
    },
}

}

Things I've tried:

  • Setting the basedir option in pug-html-loader (as you can see in the webpack.config.js)
  • Setting the static.directory and static.publicPath in devServer options (as you can see in the webpack.config.js)
  • Defining setupMiddlewares (as you can see in the webpack.config.js)

None of the above works.

If I change the links in the pug-file to http://localhost:3030/js/app.bundle.2.1.8.js and http://localhost:3030/css/app.bundle.2.1.8.css everything works as it should.

Based on the error it also seems like it tries to resolve the path based on the path where the original pug-file is located and not the static directory or the basedir defined in the webpack config.

Does anyone know how to fix it without manually defining the url with localhost:3030?

0

There are 0 answers