Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Errors don't show the exact location of the error #9

Closed
Rush opened this issue Jan 28, 2022 · 15 comments
Closed

Errors don't show the exact location of the error #9

Rush opened this issue Jan 28, 2022 · 15 comments
Labels
bug Something isn't working
Milestone

Comments

@Rush
Copy link

Rush commented Jan 28, 2022

[2] Template file: /code/nexus/portal/server/views/unsupported-browser.pug
[2] Possible reason: in the template may be used undefined variable.
[2] Solution in this case pass a variable into a pug file via the query parameter.
[2] For example, if you use in pug the external variable, like title= customData.options.title,
[2] then pass it into pug 'template.pug?customData=' + JSON.stringify({options:{title:'My title'}})
[2] TypeError: Cannot read properties of undefined (reading 'undefined')
[2]     at processResult (/code/nexus/node_modules/webpack/lib/NormalModule.js:750:12)
[2]     at /code/nexus/node_modules/webpack/lib/NormalModule.js:855:5
[2]     at /code/nexus/node_modules/loader-runner/lib/LoaderRunner.js:399:11
[2]     at /code/nexus/node_modules/loader-runner/lib/LoaderRunner.js:251:18
[2]     at runSyncOrAsync (/code/nexus/node_modules/loader-runner/lib/LoaderRunner.js:156:3)
[2]     at iterateNormalLoaders (/code/nexus/node_modules/loader-runner/lib/LoaderRunner.js:250:2)
[2]     at /code/nexus/node_modules/loader-runner/lib/LoaderRunner.js:223:4
[2]     at /code/nexus/node_modules/webpack/lib/NormalModule.js:829:15
[2]     at Array.eval (eval at create (/code/nexus/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:12:1)
[2]     at runCallbacks (/code/nexus/node_modules/enhanced-resolve/lib/CachedInputFileSystem.js:27:15)
[2]  @ ./server/views/index.ts 84:19-55
[2]  @ ./server/main.ts 29:16-34
[2]  @ ./server/mainPublic.ts 8:15-32 9:13-30

It only shows the main file where the error is, but it uses a layout which then uses a layout .. the error is hard to find.

@webdiscus
Copy link
Owner

webdiscus commented Jan 28, 2022

  1. Are you using the HtmlWebpackPlugin in your project? If yes, whether using in PUG external variables, e.g.:
div= htmlWebpackPlugin.options.title
  1. Did this bug appear after update to v1.6.3 or is it a new case?

Could you please create a simple repo with the file unsupported-browser.pug and all other dependencies in this template.
I need the source of unsupported-browser.pug and webpack.config.js.

@Rush
Copy link
Author

Rush commented Jan 31, 2022

In this case I am using the default function output. I discovered the problematic code is:

link(rel="preload" href=require('assets/fonts/ibm-plex-sans-v7-latin-regular.woff2') as="font" type="font/woff2" crossorigin)

which then goes to the webpack file-loader

This code worked with webdiscus 1.4 but broke with 1.6. I think perhaps the version should have been bumped to 2.x?

Perhaps 1.6 is doing something funky with require.

@webdiscus
Copy link
Owner

the error Cannot read properties of undefined (reading 'undefined') has not a relation with it the require().
If the required resource is not found (e.g. wrong resolved path), it will display some like Can't resolve the file ....

To locate the problem I need more information:

  1. Are you using the HtmlWebpackPlugin in your project? If yes, are external variables used in the pug template? e.g.:
div= htmlWebpackPlugin.options.title
  1. Is used Webpack 4 or 5?
  2. What version of pug-loader was used? 1.6.0, 1.6.1, 1.6.2, 1.6.3?

I have created the test case for require fonts.

With Webpack 5 it works

index.pug, where the 'assets/fonts/ is relative path by the the template

html
  head
    link(rel="preload" href=require('assets/fonts/ibm-plex-sans-v7-latin-regular.woff2') as="font" type="font/woff2" crossorigin)
  body
    p Hello World!
    img(src=require('image.jpeg'))

webpack.config.js

const path = require('path');
const PugPlugin = require('pug-plugin');

module.exports = {
  output: {
    path: path.join(__dirname, 'public/'),
    publicPath: '/',
  },

  entry: {
    index: 'src/index.pug', // the `pug-plugin` is required 
  },

  plugins: [
    new PugPlugin() //  extract HTML from pug defined in webpack entry and save to separate file
  ],

  module: {
    rules: [
      {
        test: /\.pug$/,
        loader: PugPlugin.loader, // `@webdiscus/pug-loader` is already included in PugPlugin
        options: {
          method: 'render', // export the HTML string, rendered at compile time
        },
      },

      {
        test: /\.(png|jpg|jpeg)/,
        type: 'asset/resource', // <= must be exact this to handles an image
        generator: {
          filename: 'assets/images/[name].[hash:8][ext]', // save required image under this filename
        },
      },

      {
        test: /\.(eot|ttf|woff|woff2)/,
        type: 'asset/resource',  // <= must be exact this to handles an font
        generator: {
          filename: 'assets/fonts/[name][ext]', // save required font under this filename
        },
      },
    ],
  },
};

What is difference by usage require() to compare with your case? I think the problem is elsewhere.

The file-loader is deprecated for Webpack 5, link to file-loader doc.
For Webpack 5 should be used assets module.

From ver 1.6 I have "improved" the resolving of required resources. The "interpolation" of paths was replaced with "evaluation" of once. Now is possible use a variable in require('path/to/images/${myImage}') at compile time. Added resolving of paths from tsconfig.js.

@webdiscus webdiscus added this to the analyse milestone Jan 31, 2022
@Rush
Copy link
Author

Rush commented Feb 1, 2022

Thank you for the investigation. Unfortunately I can't use the assets modules as it's not as flexible when it comes to the output paths.

I am trying to make a reproducible small test case, which is not that easy. :)

@Rush
Copy link
Author

Rush commented Feb 1, 2022

I suspect method: "compile" is for some reason not being used.

https://github.com/Rush/webdiscus-issue-9-repro

I also suspect file-loader has nothing to do with it. It's an issue purely in pug-loader. Please check out my repo and follow README.

@Rush
Copy link
Author

Rush commented Feb 1, 2022

In regards to file-loader I need more granularity as for where to output the files. I believe webpack doesn't expose such granular options for assets.

  const fileLoader = {
    loader: 'file-loader',
    options: {
      esModule: false,
      outputPath: '../public-built',
      context: path.resolve(__dirname),
      publicPath: '/',
      name: '[hash].[ext][query]'
    },
  };

@Rush
Copy link
Author

Rush commented Feb 2, 2022

Just wondering if you were able to run my repo and reproduce?

@webdiscus
Copy link
Owner

Just wondering if you were able to run my repo and reproduce?

Sorry, I am just very busy, I try your repo tomorrow.
Thank you for the repo!

@Rush
Copy link
Author

Rush commented Feb 2, 2022

Sorry, I am just very busy,

Good luck with whatever keeps you occupied! :)

I try your repo tomorrow.

Thanks!

@webdiscus
Copy link
Owner

yes, I can reproduce the issue and I found the place in the code. I will fix it.
Thank you for very important issue report.

@webdiscus
Copy link
Owner

The problem is by usage variables in template.
At pre compile time the usage of variables like opts.prop1.prop2 or opts[prop1] has issue because they are not defined. Only in runtime will be passed variables available. This is the BUG :-/

Temporary solution

Anywhere in PUG use ?. notation (node >= 14) by each variable with a property. Use this only in JS context, not in PUG context, e.g.:

you use already the correct chained properties with ?.:

 - const osName = parsedUA?.os?.name; // RIGHT!

In your template unsupported-browser.pug you should change:

this

span.browser-icon
  +svgIcon(browserIcons[recommendedBrowser])

to

span.browser-icon
  - const icons = browserIcons?.[recommendedBrowser];
  +svgIcon(icons)

and in mixin self use properties with ?.:

mixin svgIcon(iconData, currentColor = 'currentColor')
  - const [width, height, _, __, paths] = iconData?.icon || [];
  ...

I understand, this is not comfortable and tricked, sorry, but currently this works with this limitation.

P.S. I try to fix it, but it is not easy and not quick.

@Rush
Copy link
Author

Rush commented Feb 4, 2022

The workarounds seem really messy. I will stick with the old version.

Probably variable existence check should only be applied to html render mode.

@webdiscus webdiscus modified the milestones: analyse, in development Feb 6, 2022
@webdiscus
Copy link
Owner

Hello @Rush,

in the new version 1.7.0 I have fixed the issue undefined variable by usage the compile method.

This was a compromise for compile method:

  • (v1.6.x) full support for resource resolving, but object property must be used with ?.
    -VS-
  • (v1.4.x, v.1.7.x) limited support for resource resolving ( see in resolve resources the table below ) but usage an object property is w/o ?.

But the same limitation has original pug-loader. The problem is with webpack require. My solution in v1.6. was a mega useful "killer-feature", no other pug-loader does this.

Do you can please try to test the version 1.7.0?

@webdiscus webdiscus modified the milestones: in development, testing, done Feb 7, 2022
@webdiscus webdiscus added the bug Something isn't working label Feb 8, 2022
@Rush
Copy link
Author

Rush commented Feb 9, 2022

Yes thank you. This is now solved. There is another issue for which I'll open a different ticket.

@Rush Rush closed this as completed Feb 9, 2022
@Rush
Copy link
Author

Rush commented Feb 9, 2022

#10

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants