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 The router configuration from app2 The router importing app2 from app1
/* 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' } ] },
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.
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).
Webpack supports the following module types natively: ECMAScript modules. CommonJS modules. AMD modules. Assets.
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'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With