Local npm module (link) causes “Cannot assign to read only property ‘exports’ of object”

I’m creating a Vue plugin using Vue CLI 3. I was using the vue-cli-service build with target type lib to build the reusable plugin that could be imported into another project. While developing the plugin I was testing it as a local npm module (link) and I ran into this error “Cannot assign to read only property ‘exports’ of object”. I was using npm link to create a local module.

It took a lot of googling around to find the solution. It turns out it has to do with Babel and webpack. As always once you know the solution it is simple. I had to add sourceType unambiguous to my babel.config.js file. This is my babel.config.js file:

module.exports = {
  presets: [
    '@vue/app'
  ],
  sourceType: 'unambiguous'
}

This comment of a webpack issue contains the explanation. Please check it out to understand why this works.

I hope this helps someone and saves them (lots of) time.

Adding aliases with Babel

Had enough of complicated import and require statements in your Node/JavaScript files? I’m used to developing in Vue which uses Webpack aliases that by default sets up the @ alias that points to the src directory. I’m working on a project that I am using Babel but not Webpack. It turns out Babel has the cool plugin babel-plugin-module-resolver that also setup aliases.

Install the plugin.

$ npm i --save-dev babel-plugin-module-resolver

So we have the following directory structure.

project
├── src
│  └─ MyCoolService
│    └─index.js
│  └── index.js
├── test
│  └── MyCoolService.spec.js
│  .babelrc
│  package.json

In the spec file I want to test MyCoolService. Importing is messy.

import MyCoolService from '../src/MyCoolService'

I want to do it the Vue way.

import MyCoolService from '@/MyCoolService'

Can it be done? O yes, babel-plugin-module-resolver to the rescue! Create a .babelrc file with the following contents.

// .babelrc
{
  "plugins": [
    ["module-resolver", {
      "root": ["./src/**"]
      "aliases": [
        "@": "./src"
      ]
    }]
  ]
}

Now we can import with the @ alias. Alternatively as the root points to src you can also import as follows.

import MyCoolService from 'MyCoolService'

How cool is that? Happy coding!