wojtekmaj / react-pdf

Display PDFs in your React app as easily as if they were images.

Home Page:https://projects.wojtekmaj.pl/react-pdf

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Vite [ERROR] No loader is configured for ".node" files: node_modules/canvas/build/Release/canvas.node

Toxyc opened this issue · comments

Before you start - checklist

  • I followed instructions in documentation written for my React-PDF version
  • I have checked if this bug is not already reported
  • I have checked if an issue is not listed in Known issues
  • If I have a problem with PDF rendering, I checked if my PDF renders properly in PDF.js demo

Description

Recently, I migrated our project from CRA to Vite. I have tried to use v5, v6 and v7 of react-pdf. But none of them seem to work. I have folllowed the documentation guidelines for Vite but I get this error in console.

I found some other people having similar issues in NextJS in this repo, but is there a fix for Vite?
And is anyone else having this issue?

I've tried installing canvas as a package myself, also to no avail.

 [ERROR] No loader is configured for ".node" files: node_modules/canvas/build/Release/canvas.node

    node_modules/canvas/lib/bindings.js:3:25:
      3  const bindings = require('../build/Release/canvas.node')
                                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

12:36:46 PM [vite] error while updating dependencies:
Error: Build failed with 1 error:
node_modules/canvas/lib/bindings.js:3:25: ERROR: No loader is configured for ".node" files: node_modules/canvas/build/Release/canvas.node

Steps to reproduce

  1. Create vite project
  2. Use react, node and vite versions that i am using
  3. Install react-pdf
  4. Try to compile after using react-pdf import in a react component

Expected behavior

I expected Vite to compile and not crash.

Actual behavior

Vite does not compile because of react-pdf dependency canvas having issues.

Environment

  • Using Chrome on a 2019 Macbook Sonoma 14.1.2
  • React 17.0.2
  • Node 20.12.1
  • React-pdf 7.7.1
  • Vite 5.2.8

There is a sample Vite project inside this repo (/sample/vite) that definitely works just fine. There must be something different between our implementations. From your report alone though, I can't figure it out.

Using all of the sample code and package.json versions in your sample project, I still get the same errors.
Maybe this is related to the node version or the fact that this project is still running on React 17.0

I see in your sample you're using React 18.2, so I'll try to upgrade to that first, see if it fixes this issue.

Okay so I did a React upgrade to 18.2.0, with the same issue.

Changing react-pdf to v6 fixed the compiling issues for npm run start. Which makes it run locally.

However on npm run build I still get this error: "canvas" is imported by "canvas?commonjs-external", but could not be resolved – treating it as an external dependency. node_modules/pdfjs-dist/build/pdf.js (2575:23): Use of eval in "node_modules/pdfjs-dist/build/pdf.js" is strongly discouraged as it poses security risks and may cause issues with minification.

Which causes a white screen on the entire build, with the same error in the console. So the production build is still not working.

for reference this is the entire package.json file, maybe that helps to reproduce the issue.
react-pdf isn't included because it breaks the environment, but i just installed the latest version. I've also tried v5 and v6 but to no avail.

{
  "name": "redacted",
  "version": "0.1.0",
  "private": true,
  "type": "module",
  "scripts": {
    "start": "vite --host",
    "build": "vite build",
    "preview": "vite preview",
    "format": "prettier --write \"src/**/*.{js,jsx,ts,tsx}\""
  },
  "dependencies": {
    "@tanstack/react-query": "^4.35.3",
    "@xstate/react": "^3.0.0",
    "axios": "^0.26.1",
    "debounce-promise": "^3.1.2",
    "file-saver": "^2.0.5",
    "framer-motion": "^4.1.17",
    "history": "^5.3.0",
    "immer": "^9.0.15",
    "lodash": "^4.17.21",
    "luxon": "^2.4.0",
    "moment": "^2.29.4",
    "qrcode.react": "^3.1.0",
    "react": "^17.0.2",
    "react-beautiful-dnd": "^13.1.0",
    "react-datepicker": "^4.8.0",
    "react-dom": "^17.0.2",
    "react-dropzone": "^11.3.5",
    "react-helmet": "^6.1.0",
    "react-hook-form": "^6.15.4",
    "react-intersection-observer": "^9.5.3",
    "react-modal": "^3.15.1",
    "react-moment": "^1.1.3",
    "react-redux": "^7.2.8",
    "react-router-dom": "^6.3.0",
    "react-select": "^5.4.0",
    "react-tabs": "^4.2.1",
    "react-toastify": "^8.2.0",
    "react-use": "^17.4.0",
    "recharts": "^2.9.0",
    "redux": "^4.1.2",
    "redux-logger": "^3.0.6",
    "redux-persist": "^6.0.0",
    "redux-saga": "^1.1.3",
    "type-fest": "^2.3.3",
    "typescript": "^4.7.4",
    "use-http": "^1.0.26",
    "use-immer": "^0.7.0",
    "web-vitals": "^2.1.4",
    "xstate": "^4.32.1",
    "zustand": "^3.7.2"
  },
  "devDependencies": {
    "@testing-library/jest-dom": "^5.16.4",
    "@testing-library/react": "^12.1.5",
    "@testing-library/react-hooks": "^7.0.2",
    "@testing-library/user-event": "^14.2.1",
    "@types/debounce-promise": "^3.1.4",
    "@types/file-saver": "^2.0.5",
    "@types/jest": "^27.4.1",
    "@types/lodash": "^4.14.182",
    "@types/luxon": "^2.3.2",
    "@types/node": "^20.12.6",
    "@types/qrcode.react": "^1.0.2",
    "@types/react": "^17.0.2",
    "@types/react-beautiful-dnd": "^13.1.2",
    "@types/react-datepicker": "^4.4.2",
    "@types/react-dom": "^17.0.2",
    "@types/react-helmet": "^6.1.5",
    "@types/react-modal": "^3.13.1",
    "@types/react-redux": "^7.1.24",
    "@types/react-router-dom": "^5.3.3",
    "@types/react-tabs": "^2.3.4",
    "@types/redux-logger": "^3.0.9",
    "@typescript-eslint/eslint-plugin": "^5.30.5",
    "@typescript-eslint/parser": "^5.30.5",
    "@vitejs/plugin-react-swc": "^3.6.0",
    "axios-mock-adapter": "^1.21.1",
    "eslint-config-prettier": "^8.5.0",
    "eslint-plugin-prettier": "^4.2.1",
    "eslint-plugin-react": "^7.30.1",
    "husky": "^8.0.1",
    "prettier": "^2.2.1",
    "pretty-quick": "^3.1.3",
    "sass": "^1.53.0",
    "vite": "^5.2.8",
    "vite-plugin-svgr": "^4.2.0",
    "vite-tsconfig-paths": "^4.3.2"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "husky": {
    "hooks": {
      "pre-commit": "pretty-quick --staged"
    }
  }
}

To be clear, I used a stripped down version of your Vite sample and still have these issues, even with the same versions.
Any help would be appreciated!

Also could I ask what node version you are using? I am using v20.12.1

When trying to run your sample isolated from my own project, it does seem to work.
What I did not mention yet, is that we do use pdf's from a subdomain where they are hosted. so api.*.* instead of *.*.
Don't know if that makes a difference

Okay. So I found what the issue was. It's not a bug in react-pdf, sorry for wasting your time @wojtekmaj .
vitejs/vite#7376 (comment) I used this comment to fix my vite config, which had resolve: { mainFields: [], },. This caused react-pdf to not work with Vite and crash the build. Apparently it's an issue with react-moment in combination with Vite.

What I found as a different fix, that keeps both things working:
resolve: { alias: [ { // Allow moment.js to be used as an ESM module find: /^moment$/, replacement: path.resolve(__dirname, './node_modules/moment/moment.js'), }, ], },

Gonna leave this here for anyone else that might run into the same issue, although the chances are pretty slim of anyone else running into the same issue I think.

@Toxyc hello, same as me,can i get the vite.config.ts for details? the replacement value. thx.

@fguizc I ended up removing moment.js altogether, so I dont have the resolve line in my config anymore. But it is here nonetheless. If you want the fix with momentjs then you can use the line above your comment: resolve: { alias: [ { // Allow moment.js to be used as an ESM module find: /^moment$/, replacement: path.resolve(__dirname, './node_modules/moment/moment.js'), }, ], },.
vite.config.js

import { createRequire } from 'node:module';
import react from '@vitejs/plugin-react-swc';
import viteTsconfigPaths from 'vite-tsconfig-paths';
import svgr from 'vite-plugin-svgr';
import { defineConfig, normalizePath } from 'vite';
import { viteStaticCopy } from 'vite-plugin-static-copy';
import { execSync } from 'node:child_process';

const require = createRequire(import.meta.url);
const cMapsDir = normalizePath(
  path.join(path.dirname(require.resolve('pdfjs-dist/package.json')), 'cmaps'),
);
const standardFontsDir = normalizePath(
  path.join(path.dirname(require.resolve('pdfjs-dist/package.json')), 'standard_fonts'),
);

export default defineConfig(() => {
  const branchName = execSync('git rev-parse --abbrev-ref HEAD').toString().trimEnd();

  process.env.REACT_APP_BRANCH = branchName;

  return {
    envPrefix: 'REACT_APP_',
    cacheDir: '.vite',
    build: {
      outDir: 'build',
      loader: { packages: 'external' },
      sourcemap: false,
    },
    publicDir: 'public',
    server: {
      host: 'localhost',
      open: false,
      port: process.env.PORT || 3000,
    },
    define: {
      'process.env': {
        NODE_ENV: process.env.NODE_ENV,
      },
    },
    plugins: [
      react(),
      svgr({
        svgrOptions: {
          ref: true,
        },
      }),
      viteTsconfigPaths(),
      viteStaticCopy({
        targets: [
          { src: cMapsDir, dest: '' },
          { src: standardFontsDir, dest: '' },
        ],
      }),
    ],
  };
});```

@Toxyc

thx for ur reply, although we both saw the same error in the terminal, in the end I realized that it was actually because I was using the Apple M chip arm64 architecture and couldn't get the corresponding version of the compiled node-canvas file, and my node version didn't match in previous attempts, which prevented me from compiling locally as well.

image

The problem is now solved, have a nice day!