4
votes

I create a web component with vue-cli.3 in order to use it in other projects with the following command:

vue-cli-service build --target lib --name helloworld ./src/components/HelloWorld.vue

The component has a dependency on lodash. I don't want to bundle lodash with the component because lodash is going to be provided by the host application, so I configure webpack in vue.config.js like below:

module.exports = {
    configureWebpack: {
        externals: {
            lodash: 'lodash',
            root: '_'
        }
    }
}

So this way, I successfully compile the component without lodash.

In the host application (the one that will use the component), I add the source path of the newly created and compiled component into index.html:

<script src="http://localhost:8080/helloworld.umd.js"></script>

Register the component in App.vue:

<template>
    <div id="app">
        <demo msg="hello from my component"></demo>
    </div>
</template>

<script>
export default {
    name: "app",
    components: {
        demo: helloworld
    }
};
</script>

The helloworld component renders without problems. Every feature of the component works without problems but as soon as I call a method of lodash, I get;

Uncaught TypeError: Cannot read property 'camelCase' of undefined

which means the component cannot access the lodash library that the host application uses.

I need to find a way to use the already bundled libraries in the host application from the components.

Is there a way?

1
Looking at the webpack docs, it seems you have externals set up incorrectly. You need your externals object set up like this: externals: { lodash: { root: '_' } }.I don't think you really have a dependency called root that you want to be exposed as _ :p - chipit24
Another tip, if you're building a library that will be installed in another environment that includes lodash, ensure lodash is listed under peerDependencies in your package.json. - chipit24
@chipit24 You mean the package.json of the environment? Because I don't package the component, it's just a simple script file that I include in an html file which registers itself as a Vue component. - Élodie Petit
No, I mean the package.json of your library: docs.npmjs.com/files/package.json.html#peerdependencies, yarnpkg.com/lang/en/docs/dependency-types/#toc-peerdependencies. Since you're not installing your package via npm, yarn, .etc. then it technically won't make a difference. - chipit24
I don't publish a package. It's just a simple Javascript source as I've explained. - Élodie Petit

1 Answers

2
votes

The Vue config you used should work (see GitHub demo), so maybe there's something missing in your setup. I've listed the pertinent steps to arrive at the demo:

  1. In public/index.html of a VueCLI-generated project, import Lodash from CDN with:

    <script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>
    
  2. In the library component (src/components/HelloWorld.vue), the _ global can be used without importing lodash. For example, display a computed property that formats the msg prop with _.camelCase.

  3. To avoid lint errors, specify _ as an ESLint global (/* global _ */).

  4. In vue.config.js, configure Webpack to externalize lodash:

    module.exports = {
      configureWebpack: {
        externals: {
          lodash: {
            commonjs: 'lodash',
            amd: 'lodash',
            root: '_' // indicates global variable
          }
        }
      }
    }
    
  5. In package.json, edit the build script to be:

    "build": "vue-cli-service build --target lib --name helloworld ./src/components/HelloWorld.vue",
    
  6. Run npm run build, and then edit dist/demo.html to also include the <script> tag above.

  7. Start an HTTP server in dist (e.g., python -m SimpleHTTPServer), and open dist/demo.html. Observe the effect of _.camelCase (from step 2) without console errors.

GitHub demo