The following HTML demonstrates the issue:
<html>
<head>
<title>Flexpaper React/Require Sandbox</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.2.0/require.js"></script>
<script>
require(['pdf'], function(pdf) {
console.log('PDFJS Module: ' + pdf);
console.log('PDFJS Global: ' + window.PDFJS);
});
</script>
</head>
</html>
pdf.js, detects the existence of the "require" and "define" functions and accordingly does NOT set the global PDFJS instance. However, it also does not return a reference to that instance through the module loader.
Because both "pdf" and "window.PDFJS" are undefined in the example above, the library cannot be used in applications that use require. This is the case regardless of whether or not require is used to load pdf.js.
Note that this works correctly with version 1.0.1040 but fails with 1.4.20 and 1.5.188. I did not test with versions other than those 3. The behavior was consistent in all three versions between Chrome and Safari.
what's 'pdf' ? can you provide complete example?
Sure, I'll setup a Github repo to demonstrate more fully.
Here is the repo: https://github.com/MartinSnyder/pdfjs-with-requirejs
'pdf' is the module reference that require is attempting to return to that function. In that scenario, Requirejs is dynamically loading pdf.js and attempting to return the 'module reference' to the callback function, however the module reference is not set. You can see the dynamic load happen through the browser's network debugger.
This would not be that big a deal normally, except that something inside pdf.js is detecting that a module loader is present and is then NOT setting the global PDFJS object. Since neither is present, you can't use the library when requirejs is on the page.
Note that this happens even if you don't use require to load the object. I put a commented out script reference to pdf.js on the page. If that is placed before require, then the global will be set properly. If that is placed after require, then the global will NOT be set.
There are two issues with the code:
Try something like:
require.config({paths: {'pdfjs-dist': './node_modules/pdfjs-dist'}});
require(['pdfjs-dist/build/pdf'], function(pdf) {
console.log('PDFJS Module: ' + pdf + '<br>');
console.log('PDFJS Global: ' + window.PDFJS);
});
Closing as answered.
Note that this works correctly with version 1.0.1040
Working at this version is a sideeffect of requirejs loading a script as regular script tag -- does not indicate that it is a compatible with require.js
set the global PDFJS instance
Global PDFJS will be removed in future versions, so if you are using requirejs you can use the same object via pdf.PDFJS
/
With respect to point 1:
I did not use node to include pdf.js in that example. I downloaded the official distribution and copied pdf.js into the root directory of the sample. For that reason, referencing it as 'pdf' is correct. You can verify this by looking at the example in the network debugger and you will see that the file is correctly downloaded by require.
With respect to point 2:
This was done to simplify the example. Regardless of what the example does, the references are undefined and the library cannot be used. Specifically, switching to console.log also shows the references as undefined.
With respect to Global PDFJS being removed in future versions:
I'm fine with that, but how is one supposed to reference the library via pdf.PDFJS when pdf is undefined?
I did not use node to include pdf.js in that example
I did not assume you are using node.js.
downloaded the official distribution and copied pdf.js into the root directory of the sample.
PDF.js is a library and consist from many files, e.g. pdfjs-dist/build/pdf module may load pdfjs-dist/build/pdf.worker module
For that reason, referencing it as 'pdf' is correct.
You still need to use AMD name whatever is listed in the define, see https://github.com/MartinSnyder/pdfjs-with-requirejs/blob/master/pdf.js#L21
Did you try the example above with require.config pointing to the complete library?
Did you try the example above with require.config pointing to the complete library?
I just completed that now and it works as you said.
Does that mean that you cannot use the "downloaded" distribution found here for this purpose?
https://mozilla.github.io/pdf.js/getting_started/#download
So long as you use the node 'pdfjs-dist' package you are fine, but the downloaded version isn't supposed to work with this?
So long as you use the node 'pdfjs-dist' package you are fine, but the downloaded version isn't supposed to work with this?
I think it's not related to the subject, but you still can use pdf.js/pdf.worker.js files from this package, point requirejs 'pdfjs-dist' to the zipped location (it will work since pdf.js and pdf.worker.js files are located in the build folder).
You still need to use AMD name whatever is listed in the define, see https://github.com/MartinSnyder/pdfjs-with-requirejs/blob/master/pdf.js#L21
This was the key bit that I was missing from my understanding. Thank you for taking the time to explain it to me.
Hi, I have similar issue, so I am not going to open a new one, but ask here, I hope that is alright.
I am trying to implement viewer based on https://github.com/mozilla/pdf.js/blob/master/examples/components/simpleviewer.js using require.js. But when I require both pdf.js and pdf_viewer.js files, PDFJS.PDFViewer is undefined.
Here is sample repo: https://github.com/Lazzi/pdfjs-bower-requirejs
@Lazzi your main.js module looks really strange for AMD, try:
define('main', ['pdfjs-dist/build/pdf', 'pdfjs-dist/web/pdf_viewer'], function(pdfjsLib, viewer, require) {
compatibility is not AMD, so I don't know how it will work.
Yes, it is not AMD, but require.js supports also this kind of module definition: http://requirejs.org/docs/api.html#cjsmodule.
However, your proposed change didn't fix my issue..
@Lazzi I see, let's try #7332 (AFAIK AMD name matters)
@yurydelendik It works! You have been very helpful. Thank you.
this may work for you as well being placed in your require.config
map: {
'*': {
'pdfjs-dist/build/pdf.worker' : 'path/to/your/install/pdf.worker'
}
},
The map function is essentially a global string replace and the '*' is which dependencies to use the string replace for -- mostly used for including different versions of libs for other libs. Like having 2 versions of JQuery running in parallel. Be careful using -- since it only does string replacement you might end up replacing paths in other dependencies if they match.
The '*' in this case will prob only be the main pdf.js dependency.
As I was struggling a bit with correct referencing in RequireJS too, I will leave my solution, which is part of the RequireJS config:
paths: {
'pdfjs-dist/build/pdf': 'myfolder/pdf.min',
'pdfjs-dist/build/pdf.worker': 'myfolder/pdf.worker.min'
}
When you do it like that, you do not even have to assign the path to the worker to PDFJS.workerSrc
, as suggested in the examples, because the worker will be found automatically.
Thank you @dmaxweiler! I struggled with the same issue -- I was having trouble getting pdf.js to load correctly when using RequireJS also. Your solution worked for me! Awesome. Thanks for your help.
Most helpful comment
As I was struggling a bit with correct referencing in RequireJS too, I will leave my solution, which is part of the RequireJS config:
When you do it like that, you do not even have to assign the path to the worker to
PDFJS.workerSrc
, as suggested in the examples, because the worker will be found automatically.