webdiscus / pug-loader

Pug loader for Webpack renders pug to HTML or template function
https://webdiscus.github.io/pug-loader/pug-filters
ISC License
72 stars 5 forks source link

`include` doesn't use dynamic `resolve.alias` (from tsconfig-paths-webpack-plugin) #6

Closed XenoBino closed 2 years ago

XenoBino commented 2 years ago

Description

Sorry for my bad English as my mother tongue is not English. I use tsconfig-paths-webpack-plugin to add resolve.alias in webpack. Other loaders like sass-loader are totally fine with the alias, but pug compilation fails which leads me to believe that the problem is in this loader.

Info

OS Windows 11
Node v14.17.1
Package manager yarn
yarn version 1.22.17
@webdiscus/pugloader version 1.5.1

Temporary solution (until fixed)

While writing this issue I tried different temporary solutions which all had a problem in a way or other thus I suggest that you manually add the needed paths to resolve.alias in your webpack config.

Build log

D:\pug-loader-bug>webpack
assets by status 10.7 KiB [cached] 2 assets
runtime modules 663 bytes 3 modules
modules by path ../node_modules/ 8.07 KiB
  modules by path ../node_modules/style-loader/dist/runtime/*.js 5.75 KiB
    ../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js 2.44 KiB [built] [code generated]
    ../node_modules/style-loader/dist/runtime/styleDomAPI.js 1.38 KiB [built] [code generated]
    ../node_modules/style-loader/dist/runtime/insertBySelector.js 1010 bytes [built] [code generated]
    ../node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js 300 bytes [built] [code generated]
    ../node_modules/style-loader/dist/runtime/insertStyleElement.js 286 bytes [built] [code generated]
    ../node_modules/style-loader/dist/runtime/styleTagTransform.js 382 bytes [built] [code generated]
  modules by path ../node_modules/css-loader/dist/runtime/*.js 2.33 KiB
    ../node_modules/css-loader/dist/runtime/noSourceMaps.js 64 bytes [built] [code generated]
    ../node_modules/css-loader/dist/runtime/api.js 2.26 KiB [built] [code generated]
modules by path ./views/*.scss 1.66 KiB
  ./views/index.scss 1.22 KiB [built] [code generated]
  ../node_modules/css-loader/dist/cjs.js!../node_modules/sass-loader/dist/cjs.js!./views/index.scss 447 bytes [built] [code generated]

WARNING in configuration
The 'mode' option has not been set, webpack will fallback to 'production' for this value.
Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
You can also set it to 'none' to disable any default behavior. Learn more: https://webpack.js.org/configuration/mode/

ERROR in   Error: Child compilation failed:
  Module build failed (from ../node_modules/@webdiscus/pug-loader/src/index.js):
  NonErrorEmittedError: (Emitted value instead of an instance of Error)
  [pug-loader] Pug compilation failed.
  Error: ENOENT: no such file or directory, open 'D:\pug-loader-bug\src\views\@component\nav.pug'
      at D:\pug-loader-bug\src\views\index.pug line 1
      at processResult (D:\pug-loader-bug\node_modules\webpack\lib\NormalModule.js:748:12)
      at D:\pug-loader-bug\node_modules\webpack\lib\NormalModule.js:853:5
      at D:\pug-loader-bug\node_modules\loader-runner\lib\LoaderRunner.js:399:11
      at D:\pug-loader-bug\node_modules\loader-runner\lib\LoaderRunner.js:251:18
      at context.callback (D:\pug-loader-bug\node_modules\loader-runner\lib\LoaderRunner.js:124:13)
      at D:\pug-loader-bug\node_modules\@webdiscus\pug-loader\src\index.js:175:21
      at Object.compilePugContent (D:\pug-loader-bug\node_modules\@webdiscus\pug-loader\src\index.js:150:5)
      at Object.module.exports (D:\pug-loader-bug\node_modules\@webdiscus\pug-loader\src\index.js:174:21)
  ModuleBuildError: Module build failed (from ../node_modules/@webdiscus/pug-loader/src/index.js):
  NonErrorEmittedError: (Emitted value instead of an instance of Error)
  [pug-loader] Pug compilation failed.
  Error: ENOENT: no such file or directory, open 'D:\pug-loader-bug\src\views\@component\nav.pug'
      at D:\pug-loader-bug\src\views\index.pug line 1
      at processResult (D:\pug-loader-bug\node_modules\webpack\lib\NormalModule.js:748:12)
      at D:\pug-loader-bug\node_modules\webpack\lib\NormalModule.js:853:5
      at D:\pug-loader-bug\node_modules\loader-runner\lib\LoaderRunner.js:399:11
      at D:\pug-loader-bug\node_modules\loader-runner\lib\LoaderRunner.js:251:18
      at context.callback (D:\pug-loader-bug\node_modules\loader-runner\lib\LoaderRunner.js:124:13)
      at D:\pug-loader-bug\node_modules\@webdiscus\pug-loader\src\index.js:175:21
      at Object.compilePugContent (D:\pug-loader-bug\node_modules\@webdiscus\pug-loader\src\index.js:150:5)
      at Object.module.exports (D:\pug-loader-bug\node_modules\@webdiscus\pug-loader\src\index.js:174:21)
      at processResult (D:\pug-loader-bug\node_modules\webpack\lib\NormalModule.js:751:19)
      at D:\pug-loader-bug\node_modules\webpack\lib\NormalModule.js:853:5
      at D:\pug-loader-bug\node_modules\loader-runner\lib\LoaderRunner.js:399:11
      at D:\pug-loader-bug\node_modules\loader-runner\lib\LoaderRunner.js:251:18
      at context.callback (D:\pug-loader-bug\node_modules\loader-runner\lib\LoaderRunner.js:124:13)
      at D:\pug-loader-bug\node_modules\@webdiscus\pug-loader\src\index.js:175:21
      at Object.compilePugContent (D:\pug-loader-bug\node_modules\@webdiscus\pug-loader\src\index.js:150:5)
      at Object.module.exports (D:\pug-loader-bug\node_modules\@webdiscus\pug-loader\src\index.js:174:21)
      at LOADER_EXECUTION (D:\pug-loader-bug\node_modules\loader-runner\lib\LoaderRunner.js:132:14)
      at runSyncOrAsync (D:\pug-loader-bug\node_modules\loader-runner\lib\LoaderRunner.js:133:4)

  - NormalModule.js:748 processResult
    [pug-loader-bug]/[webpack]/lib/NormalModule.js:748:12

  - NormalModule.js:853
    [pug-loader-bug]/[webpack]/lib/NormalModule.js:853:5

  - LoaderRunner.js:399
    [pug-loader-bug]/[loader-runner]/lib/LoaderRunner.js:399:11

  - LoaderRunner.js:251
    [pug-loader-bug]/[loader-runner]/lib/LoaderRunner.js:251:18

  - LoaderRunner.js:124 context.callback
    [pug-loader-bug]/[loader-runner]/lib/LoaderRunner.js:124:13

  - index.js:175
    [pug-loader-bug]/[@webdiscus]/pug-loader/src/index.js:175:21

  - index.js:150 Object.compilePugContent
    [pug-loader-bug]/[@webdiscus]/pug-loader/src/index.js:150:5

  - index.js:174 Object.module.exports
    [pug-loader-bug]/[@webdiscus]/pug-loader/src/index.js:174:21

  - ModuleBuildError: Module build failed (from ../node_modules/@webdiscus/pug-loader/src/index.js):

  - NonErrorEmittedError: (Emitted value instead of an instance of Error)

  - [pug-loader] Pug compilation failed.

  - Error: ENOENT: no such file or directory, open 'D:\pug-loader-bug\src\views\@component\nav.pug'

  - NormalModule.js:748 processResult
    [pug-loader-bug]/[webpack]/lib/NormalModule.js:748:12

  - NormalModule.js:853
    [pug-loader-bug]/[webpack]/lib/NormalModule.js:853:5

  - LoaderRunner.js:399
    [pug-loader-bug]/[loader-runner]/lib/LoaderRunner.js:399:11

  - LoaderRunner.js:251
    [pug-loader-bug]/[loader-runner]/lib/LoaderRunner.js:251:18

  - LoaderRunner.js:124 context.callback
    [pug-loader-bug]/[loader-runner]/lib/LoaderRunner.js:124:13

  - index.js:175
    [pug-loader-bug]/[@webdiscus]/pug-loader/src/index.js:175:21

  - index.js:150 Object.compilePugContent
    [pug-loader-bug]/[@webdiscus]/pug-loader/src/index.js:150:5

  - index.js:174 Object.module.exports
    [pug-loader-bug]/[@webdiscus]/pug-loader/src/index.js:174:21

  - NormalModule.js:751 processResult
    [pug-loader-bug]/[webpack]/lib/NormalModule.js:751:19

  - NormalModule.js:853
    [pug-loader-bug]/[webpack]/lib/NormalModule.js:853:5

  - LoaderRunner.js:399
    [pug-loader-bug]/[loader-runner]/lib/LoaderRunner.js:399:11

  - LoaderRunner.js:251
    [pug-loader-bug]/[loader-runner]/lib/LoaderRunner.js:251:18

  - LoaderRunner.js:124 context.callback
    [pug-loader-bug]/[loader-runner]/lib/LoaderRunner.js:124:13

  - index.js:175
    [pug-loader-bug]/[@webdiscus]/pug-loader/src/index.js:175:21

  - index.js:150 Object.compilePugContent
    [pug-loader-bug]/[@webdiscus]/pug-loader/src/index.js:150:5

  - index.js:174 Object.module.exports
    [pug-loader-bug]/[@webdiscus]/pug-loader/src/index.js:174:21

  - LoaderRunner.js:132 LOADER_EXECUTION
    [pug-loader-bug]/[loader-runner]/lib/LoaderRunner.js:132:14

  - LoaderRunner.js:133 runSyncOrAsync
    [pug-loader-bug]/[loader-runner]/lib/LoaderRunner.js:133:4

  - child-compiler.js:169
    [pug-loader-bug]/[html-webpack-plugin]/lib/child-compiler.js:169:18

  - Compiler.js:559
    [pug-loader-bug]/[webpack]/lib/Compiler.js:559:11

  - Compiler.js:1129
    [pug-loader-bug]/[webpack]/lib/Compiler.js:1129:17

  - Hook.js:18 Hook.CALL_ASYNC_DELEGATE [as _callAsync]
    [pug-loader-bug]/[tapable]/lib/Hook.js:18:14

  - Compiler.js:1125
    [pug-loader-bug]/[webpack]/lib/Compiler.js:1125:33

  - Compilation.js:2782 finalCallback
    [pug-loader-bug]/[webpack]/lib/Compilation.js:2782:11

  - Compilation.js:3087
    [pug-loader-bug]/[webpack]/lib/Compilation.js:3087:11

  - Hook.js:18 Hook.CALL_ASYNC_DELEGATE [as _callAsync]
    [pug-loader-bug]/[tapable]/lib/Hook.js:18:14

1 ERROR in child compilations (Use 'stats.children: true' resp. '--stats-children' for more details)
webpack 5.65.0 compiled with 2 errors and 1 warning in 1819 ms

Steps to reproduce

Clone the following directory structure and file contents:

Directory structure

package.json
tsconfig.json
yarn.lock
webpack.config.js
src/
|__views
|____index.pug
|____index.scss
|__components
|____nav.pug
|____nav.scss

File contents

package.json

{
  "devDependencies": {
    "@webdiscus/pug-loader": "^1.5.1",
    "css-loader": "^6.5.1",
    "html-webpack-plugin": "^5.5.0",
    "pug": "^3.0.2",
    "sass": "^1.46.0",
    "sass-loader": "^12.4.0",
    "style-loader": "^3.3.1",
    "tsconfig-paths-webpack-plugin": "^3.5.2",
    "webpack": "^5.65.0",
    "webpack-cli": "^4.9.1"
  }
}

tsconfig.json

{
  "compilerOptions": {
    "baseUrl": "src",
    "paths": {
      "@components/*": ["components/*"],
    }
  }
}

webpack.config.js

let TsConfigPathsPlugin = require("tsconfig-paths-webpack-plugin");
let HtmlWebpackPlugin = require("html-webpack-plugin");
let path = require("path");

let helpers = {
  root(...paths) {
    return path.join(__dirname, ...paths);
  },

  src(...paths) {
    return path.join(__dirname, "src/", ...paths);
  },

  dist(...paths) {
    return path.join(__dirname, "dist/", ...paths);
  }
};

module.exports = {
  context: helpers.src(),
  entry: "views/index.scss", // Explaination below...
  resolve: {
    plugins: [
      new TsConfigPathsPlugin({
        configFile: helpers.root("tsconfig.json")
      })
    ]
  },
  output: {
    path: helpers.dist()
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: "views/index.pug"
    })
  ],
  module: {
    rules: [
      /**
        * Why scss loader?
        * If scss-loader can use the aliases defined in tsconfig.json,
        * then the issue isn't from tsconfig-path-webpack-plugin.
        */
      {
        test: /\.(?:s[ca]|c)ss$/i,
        use: ["style-loader", "css-loader", "sass-loader"]
      },
      {
        test: /\.pug$/i,
        use: "@webdiscus/pug-loader"
      }
    ]
  }
};

views/index.pug

include @components/nav

views/index.scss

@use "@components/nav.scss";

components/nav.pug

p.nav Hello World

components/nav.scss

.nav {
  color: red;
}
webdiscus commented 2 years ago

Hello @XenoBino,

thank you for the bug report! I will try reproduce it by me local.

webdiscus commented 2 years ago

Hello @XenoBino

  1. you has the error in views/index.pug by alias @component/, is missed the s at end. Please edit your message. include @component/nav ==> include @components/nav
  2. current this plugin support only resolve.alias
  3. the temporary solution your problem is usage resolve.alias:
     resolve: {
       //plugins: [tsConfig], // this is not supported
       alias: {
        '@components': helpers.src('components'), // this works
      },
     },
webdiscus commented 2 years ago

Hello @XenoBino ,

Good news, I've taken the time to improve the alias resolving. I already have positive results. Soon I release next version with support of resolve.plugins.

XenoBino commented 2 years ago

Hi @webdiscus, Thank you for taking time to review and fix the issue. I am about to meet a deadline in a project I am working on, and the paths/resolve.alias issues was really frustrating and time consuming to deal with, so I really appreciate all the effort spent in solving this issue.

In reply to 3 in your second comment, I tried using resolve.alias as a substitute to paths in my project, but it seems that the typescript loader, @ngtools/webpack, doesn't honor aliases defined their. In my free time I tested @ngtools/webpack with resolve.alias in an empty project, and strangely it worked. I might also open an issue in @ngtools/webpack about this.

Generally, I suggest not to use resolve.alias with typescript, since IDEs and editors will not understand imports.

webdiscus commented 2 years ago

Hello @XenoBino,

I have added support for resolve.plugins. Currently it works only for extends and include, not for require(), because for it used the complex Interpolation. To resolve embedded resources via require() use alias. The very fast resolve.alias will be used first, if nothing is resolved then the slow webpack resolver will be used.

Warning: using a resolver other than resolve.alias can seriously degrade performance.

Please try the new NPM package ^1.6.2. Here is the test case for resolve.plugins .

webdiscus commented 2 years ago

Hello @XenoBino, can you please test new fixed version 1.6.2 and if all is ok than close this issue?

XenoBino commented 2 years ago

Hello @webdiscus, My apologies for the late reply, I have been busy the past month. After 1.6.0-alpha1, the loader began to have issues with hot module replacement which might mean that files are not being added to the dependency tree thus not watched. I have updated to 1.7.1 and the issue continued. I might rollback to 1.5.* till this feature is stable.

Additionally I suggest adding an option to enable (making it disabled by default) the behavior added after this issue as it slows the build process. Also I believe that it is uncommon for a developer to have the same case described above.

webdiscus commented 2 years ago

Hello @XenoBino,

possible that the problem with watching of dependencies has a relation with the issue path errors on Windows. This issue was fixed in new version 1.7.3. Note: by webpack serv the live reload of browser after rebuild is not supported.

webdiscus commented 2 years ago

The new resolver in pug-loader firstly try to resolve an alias from resolve.alias (this is fastest method), then if alias not resolved try to resolve with slow enhanced-resolver to resolve from resolve.plugins.

Tips

To speed up the build process should be used resolve.alias only. Each item in alias should be a string. If alias is array of paths, will be used slow enhanced-resolver.

XenoBino commented 2 years ago

Hello, @webdiscus.

I ran a few tests and everything seems to be working correctly after I upgraded to 1.7.3. Build time became 81s (2.5s or less incremental) on my mid tier device.

Thanks for taking time to solve these issues.

webdiscus commented 2 years ago

Hello @XenoBino,

thanks for the feedback :-)