Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Webpack Cannot Resolve node_modules lazy assets

I'm working on a vuejs project and we're trying to use external vue cli applications as libraries. In these libraries we want to be able to export a router config, which lazy loads the components within one of these modules. However when we compile this using the vue-cli-service into a library and it's got lazy chunk assets we cannot resolve them with webpack.

I have a feeling its something to do with the public path, or some simple configuration but i'm just stuck and banging my head against a wall at this stage with it.

https://github.com/EvanBurbidge/mono-repo-tester

Here's a simple overview of what we're doing

App1 -> main app, installs App2, imports { router } from 'app2'
App2 -> library, compiles to common js lib exports router config

The console output from app1 see_screenshot_1 The router configuration from app2 see_screenshot_2 The router importing app2 from app1 see_screenshot_3

/* config.module.rule('js') */ { test: /\.jsx?$/, exclude: [ function () { /* omitted long function */ } ], use: [ /* config.module.rule('js').use('cache-loader') */ { loader: 'cache-loader', options: { cacheDirectory: '/Users/evan/test/node_modules/.cache/babel-loader', cacheIdentifier: '39e7e586' } }, /* config.module.rule('js').use('babel-loader') */ { loader: 'babel-loader' } ] },

like image 349
Evan Burbidge Avatar asked Jan 11 '19 15:01

Evan Burbidge


People also ask

Does Webpack include Node_modules?

Webpack builds a dependency graph used internally Now all modules that are used in your app are included in the dependency graph. Your project have many installed dependencies in the node_modules folder that should not be included in your client-side JavaScript production bundle.

How does Webpack lazy loading work?

You can load only the files you want and improve your app's performance. Webpack allows you to lazy load 3rd-party libraries, and, even better, it allows you to chunk your own app and lazy load parts of it on demand. Webpack has implemented the ES7 dynamic import spec (available in Chrome and Safari).

What are modules in Webpack?

Webpack supports the following module types natively: ECMAScript modules. CommonJS modules. AMD modules. Assets.


1 Answers

I think I know what the problem is.

It appears that you're suffering from the fact that the default config of webpack bundled with VueJS does not support what you are trying to accomplish. In fact, it may very well be that Webpack does not support what you are trying to accomplish #2471 #6818 #7843.

When you compile app2 into UMD and try to use it within app1 by importing the UMD, the dynamic imports of app2 are not being resolved and are thus not copied over to the publicPath of app1. Since it is a dynamic import, compilation succeeds to the point where you can deploy the app. When you try to load the app however, it starts complaining that chunks are missing.

Here's one way to solve this problem:

app2/package.json

{
  "name": "app2",
  ...
  "main": "src/router.js"
}

app2/src/router.js

const Hey = () => import(/*webpackChunkName: 'app2.Hello.vue' */ './components/HelloWorld.vue')

export default [
  {
    path: '/app2',
    component: Hey,
    name: 'app2.hey'
  }
]

app1/router.js

import app2Router from 'app2'
import Home from './views/Home.vue'

export default new Router([
  mode: 'history',
  ...
  routes: [
    {
      path: '/',
      name: 'home',
      component: Home
    },
    ...app2Router
  ]
])

By marking the main or module of app2/package.json as router.js instead of the the UMD bundle, you are forcing app1 to build the whole dependency graph and include any dynamic import that is detected. This in turn causes the dependencies to be copied over properly.

You could also achieve the exact same results by using

import app2Router from 'app2/src/router'
like image 74
Guru Prasad Avatar answered Nov 09 '22 08:11

Guru Prasad