webpacker: "Uncaught TypeError: root is undefined" when importing from package

I am a bit heavily lost in the quest for a solution to my problem, so apologies if this is not the right place for my question. It appeared the least wrong one to start with and I happily take recommendations where to go with it otherwise.

I want to setup pdf.js in our Rails app and followed the recommendation for webpack users which basically says to simply use import pdfjsLib from 'pdfjs-dist/webpack'; which takes care of setting up the worker. With this code in my JavaScript I get the following error in my browser console when I access a page that triggers this code:

Uncaught TypeError: root is undefined
    webpackUniversalModuleDefinition pdf.js:77
    js                               pdf.js:78

I cannot find the respective code in the pdf.js repository, I assume it is generated by some build/release pipeline. But here is what the respective file in node_modules/pdfjs-dist/build/pdf.js looks like. It starts with something that appears to me like something webpack specific:

(function webpackUniversalModuleDefinition(root, factory) {
	if(typeof exports === 'object' && typeof module === 'object')
		module.exports = factory();
	else if(typeof define === 'function' && define.amd)
		define("pdfjs-dist/build/pdf", [], factory);
	else if(typeof exports === 'object')
		exports["pdfjs-dist/build/pdf"] = factory();
	else
		root["pdfjs-dist/build/pdf"] = root.pdfjsLib = factory();
})(this, function() {
// all the code
});

The flagged lines belong to the body of a function defined like this:

// define __esModule on exports
__w_pdfjs_require__.r = function(exports) {
  if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {                  // <-- Line 77
    Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); // <-- Line 78
  }
  Object.defineProperty(exports, '__esModule', { value: true });
};

A gist with the complete pdf.js from the pdfjs-dist package can be viewed here

That is my situation and I am lost between webpacker, webpack and pdf.js. My intuition was that I probably need to tell webpack(er?) that it should inject something for the root value. However, this is a formal parameter of the module definition as far as I see it. So what value for what keyword would I have to inject exactly and where? I was down to the imports-loader for webpack but either did not figure out how to correctly embed its rules in the webpack config in config/webpack/environment.js. I try & only-errored for some time and gave up.

On the other hand I think/hope/assume that it should be possible to somehow only do what the README for pdf.js says: Import the thing via webpack.js. After all it is advertised as the zero-configuration method for Webpack users and I would like to be one of that happy users. Maybe I am only missing something very simple that is painfully obvious if you know it … but I just don’t know and couldn’t figure out in three days so far. So, anyone a hint or maybe even the solution? 😃

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 16 (4 by maintainers)

Most upvoted comments

@RST-J I think I found out what’s going on. I’ve got pdf.js working for Webpacker 5 in the demo/webpacker-5 branch. Could you test my fix described below?

There was a problem with the Webpacker 5 config after all (it’s fixed in Webpacker 6). To fix in your project on Webpacker 5, you’ll want to disable the default Webpacker loader rule for processing node_modules. To do so, your config should look something like the following:

// config/webpack/environment.js

const { environment } = require('@rails/webpacker')

environment.loaders.delete('nodeModules') // <== deletes Webpacker loader rule for node_modules

module.exports = environment

Webpacker 5 is configured to run Babel transpilation on your node_modules libraries—turns out this caused a lot of unexpected bugs. You can read more about the history in this PR.

Apologies, this should have occurred to me earlier. Let me know if this works for you.

I have a working demo of integrating Webpacker 6.0.0.beta.5 with PDF.js: https://github.com/rossta/webpacker-6.0.0.beta-pdfjs-demo

The main issue I ran into is that the main 'pdfjs-dist' package does not appear to work as an ES module, so import pdfjs from 'pdfjs-dist/webpack' results in an undefined import. However, const pdfjs = require('pdfjs-dist/webpack') does work as expected.

There is a mirror site which packages 'pdfjs-dist' as an ES module; I would expect normal ES import syntax would work for you if you choose this distribution.

Hope that’s helpful.

We indeed had issues with deleting the loader altogether, namely IE compatibility of some packages we use. After all, this is what babel is there for, so we shouldn’t be too surprised about that. Depending on what libraries you include and which modern JS features they use, you could face similar problems even with current browsers that might be hard to detect. We defused the fix for the original issue to be more specific and only exclude the pdfjs package from transpilation:

// config/webpack/environment.js
const { environment } = require('@rails/webpacker')
let nodeModules = environment.loaders.find(loader => loader.key === 'nodeModules')
nodeModules.value.exclude = new RegExp(nodeModules.value.exclude.source + "|pdf")
module.exports = environment

@Genkilabs I don’t know your stack so I’m making assumptions, but I doubt you’ll have issues with this change as it’s not likely for libraries to require you to run babel transpilation on their contents to be used.

@RST-J I have a WORKAROUND for running pdf.js on Rails 6.1 Ruby 3.0 with webpacker. This Gist is not as good as if pdf.js exported correctly, but it will get you through the day.

https://gist.github.com/Genkilabs/a5285020ca548f589b9c46497afca941

NOTE: I did NOT do anything like require('pdfjs-dist/es5/build/pdf') in my application.js and I did not import it in my module, because its a globally-scoped kludgearound!