Search code examples
node.jsnpmxlsx

Import * as not working as expected in node


I want to use the xlsx module for reading and writing to xlsx files, so I installed xlsx by running npm install xlsx and I followed a tutorial where it was mentioned that:

// Requiring the module 
const reader = require('xlsx') 
  
// Reading our test file 
const file = reader.readFile('./test.xlsx') 

It was working fine, but I was using another module that wasn't a CommonJS module, so I used:

import reader from 'xlsx';

const file = reader.readFile('./test.xlsx');

It is also working, but my question is: I am able to use anything in place of reader and still able to access the method readFile. E.g.:

import anyRandomWord from 'xlsx';

const file = anyRandomWord.readFile('./test.xlsx');

NOW THE CASES THAT ARE NOT WORKING:

  1. The official site says that:

The module also ships with xlsx.mjs for use with import:

import * as XLSX from 'xlsx/xlsx.mjs';

when I use:

import * as XLSX from 'xlsx/xlsx.mjs';

const file = XLSX.readFile('./test.xlsx');

I get the error:

Error: Cannot access file ./test.xlsx
    at read_binary (file:///home/shivam/Others/Translate/node_modules/xlsx/xlsx.mjs:3234:8)
    at readSync (file:///home/shivam/Others/Translate/node_modules/xlsx/xlsx.mjs:23811:69)
    at Module.readFileSync (file:///home/shivam/Others/Translate/node_modules/xlsx/xlsx.mjs:23851:9)
    at file:///home/shivam/Others/Translate/translate.js:4:19
    at ModuleJob.run (node:internal/modules/esm/module_job:218:25)
    at async ModuleLoader.import (node:internal/modules/esm/loader:329:24)
    at async loadESM (node:internal/process/esm_loader:28:7)
    at async handleMainPromise (node:internal/modules/run_main:120:12)

when I use:

import * as XLSX from 'xlsx';

const file = XLSX.readFile('./test.xlsx');

I get the error:

TypeError: XLSX.readFile is not a function
    at file:///home/shivam/Others/Translate/translate.js:4:19
    at ModuleJob.run (node:internal/modules/esm/module_job:218:25)
    at async ModuleLoader.import (node:internal/modules/esm/loader:329:24)
    at async loadESM (node:internal/process/esm_loader:28:7)
    at async handleMainPromise (node:internal/modules/run_main:120:12)

Please tell me why the above cases are working with any random name in import and the below ones are not working.

I have added "type":"module" in package.json


Solution

  • when I use

    import * as XLSX from 'xlsx/xlsx.mjs';
    
    const file = XLSX.readFile('./test.xlsx');
    

    I get the error

    Error: Cannot access file ./test.xlsx

    As mentioned in the doc regarding usage of the xlsx/xlsx.mjs module version:

    The mjs version does not automatically load native node modules, so they must be added manually:

    import * as XLSX from 'xlsx';
    
    /* load 'fs' for readFile and writeFile support */
    import * as fs from 'fs';
    XLSX.set_fs(fs);
    

    I am able to use anything in place of reader and still able to access the method readFile

    ...and:

    when I use

    import * as XLSX from 'xlsx';
    
    const file = XLSX.readFile('./test.xlsx');
    

    I get the error

    TypeError: XLSX.readFile is not a function

    The xlsx package has a default export, which you can import with any name you want, as you figured out initially (i.e. import anyRandomWord from 'xlsx').

    But when you import the namespace (i.e. import * as XLSX), that default export is now a property of your namespace, i.e. you should now do XLSX.default.readFile():

    The default export available as a key called default.