javascriptmodulerollup

Bundling javascript module issue


I'm very new to programming in javascript. I'm trying to bundle two modules via rollup. I'm trying to import a file - cars.js - into my index.js file.

Code for cars.js

const carsJSON = `[
    {
        "make": "Honda",
        "model": "Accord",
        "year": 1997,
        "price": 2800
    },
    {
        "make": "Toyota",
        "model": "Fortunner",
        "year": 2001,
        "price": 3500
    },
     {
        "make": "Hyundai",
        "model": "i20",
        "year": 2005,
        "price": 3000
    },
    {
        "make": "Maruti Suzuki",
        "model": "WagonR",
        "year": 1995,
        "price": 1200
    }
]`

export const cars = JSON.parse(carsJSON);

Here's the code for index.js

import { cars } from 'cars.js';

const message = cars[0].make;

And the code for bundle.js that was created

!function(s){"use strict";s.cars[0].make}(cars_js);
//# sourceMappingURL=bundle.js.map

But, when I'm loading the .html file on my local server I'm getting this error -

index.js:3 Uncaught ReferenceError: cars_js is not defined
    at index.js:3:25

Here's the package.json that was created

{
  "name": "bundler",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "rollup -c",
    "watch": "rollup -c -w"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": "",
  "devDependencies": {
    "@babel/preset-react": "^7.24.7",
    "@rollup/plugin-babel": "^6.0.4",
    "@rollup/plugin-commonjs": "^26.0.1",
    "@rollup/plugin-node-resolve": "^15.2.3",
    "@rollup/plugin-replace": "^5.0.7",
    "@rollup/plugin-terser": "^0.4.4",
    "rollup": "^2.79.1",
    "rollup-plugin-terser": "^7.0.2"
  }
}

and the rollup.config.js

import resolve from '@rollup/plugin-node-resolve';
import commonjs from '@rollup/plugin-commonjs';
import babel from '@rollup/plugin-babel';
import replace from '@rollup/plugin-replace';
import { terser } from 'rollup-plugin-terser';

export default {
  input: 'src/index.js',
  output: {
    file: 'build/bundle.js',
    format: 'iife', // Immediately Invoked Function Expression
    sourcemap: true,
  },
  plugins: [
    resolve(),
    commonjs(),
    babel({
      exclude: 'node_modules/**',
      presets: ['@babel/preset-react'],
    }),
    replace({
      'process.env.NODE_ENV': JSON.stringify('production'),
      preventAssignment: true,
    }),
    terser(),
  ],
};

Is there any issue with the bundling or how do I fix the error?


Solution

  • Your cars.js file should be exporting a default array of car objects.

    export default [
      {
        make: "Honda",
        model: "Accord",
        year: 1997,
        price: 2800,
      },
      {
        make: "Toyota",
        model: "Fortunner",
        year: 2001,
        price: 3500,
      },
      {
        make: "Hyundai",
        model: "i20",
        year: 2005,
        price: 3000,
      },
      {
        make: "Maruti Suzuki",
        model: "WagonR",
        year: 1995,
        price: 1200,
      },
    ];
    

    And you should import is as:

    import cars from './cars.js'; // Note the relative path
    

    Make sure that cars.js is a sibling of your index.js file.


    Update

    In regards to this IIFE:

    !function(s){"use strict";s.cars[0].make}(cars_js);
    

    The loaded cars_js above is an array, since I changed it to a default export. It is trying to access a cars field on the scope, but it is an array now.

    To fix this, you might need to change it back to a named export for it to work:

    export const cars = [
      {
        make: "Honda",
        model: "Accord",
        year: 1997,
        price: 2800,
      },
      {
        make: "Toyota",
        model: "Fortunner",
        year: 2001,
        price: 3500,
      },
      {
        make: "Hyundai",
        model: "i20",
        year: 2005,
        price: 3000,
      },
      {
        make: "Maruti Suzuki",
        model: "WagonR",
        year: 1995,
        price: 1200,
      },
    ];
    

    Or:

    const cars = [
      {
        make: "Honda",
        model: "Accord",
        year: 1997,
        price: 2800,
      },
      {
        make: "Toyota",
        model: "Fortunner",
        year: 2001,
        price: 3500,
      },
      {
        make: "Hyundai",
        model: "i20",
        year: 2005,
        price: 3000,
      },
      {
        make: "Maruti Suzuki",
        model: "WagonR",
        year: 1995,
        price: 1200,
      },
    ];
    
    export { cars };