12

I have 2 Vue applications and they both need to use some common pages and assets (scss files, icons etc.).

The pages they need to share are full pages with access to vuex store and async calls.

What I think to do is to create a single vue app (with the cli) and put both the apps in it and have a shared folder:

vue-project
   - src
     - app1
     - app2
     - shared

But then I have a problem: How do I build/run each app separately?

Tomer
  • 17,787
  • 15
  • 78
  • 137

3 Answers3

17

UPDATE 2022

The solution I offer below is valid but it's hard to manage and adding new projects is very involved.

Today there are many monorepo tools that are better at managing these types of projects:

  1. nx
  2. yarn workspaces

these are just a couple of options but many more exist

ORIGINAL POST

So this is what I ended up doing:

  • I've created this structure

     vue-project
         - node_modules
         - src
           - app1
           - app2
           - shared
    
  • All node modules are under vue-project, so they are shared

  • Not mandatory, but I defined aliases for the different projects:

     ...
     "@app1": path.resolve(__dirname, "src/app1"),
     "@app2": path.resolve(__dirname, "src/app2"),
     "@shared": path.resolve(__dirname, "src/shared/components")
     ...
    
  • It's important to note, that when creating the aliases you should add the '@' symbol, or else you might get unexpected results. For me, before I added it, it was loading resources from app2 even though I used the alias of app1

  • I've created these scripts in package.json:

     "serve:app1": "vue-cli-service serve --port 3000 --open  src/app1/main.js",
     "serve:app2": "vue-cli-service serve --port 3001 --open  src/app2/main.js",
     "build:app1": "vue-cli-service build --dest dist/console src/app1/main.js",
     "build:app2": "vue-cli-service build --dest dist/tm src/app2/main.js"
    

And that's basically it, I now have 2 separate vue apps running and sharing components, store modules, and pages.

Tomer
  • 17,787
  • 15
  • 78
  • 137
  • 1
    Interesting idea. Now, you share`package.json`because your 2 apps are close enough to do so? – titou10 May 27 '19 at 15:08
  • It s a pragmatic solution. Easy to use, very effecient when you work inside your project (not need to jump between 3 projects) but all projects share the config, env variables, ... How do you handle public/index.html (and public/sitemap.xml) with your solution ? – rdhainaut Mar 25 '20 at 18:48
  • It's an enterprise Single page app, so there is no sitemap.xml, also, each app get it's own index.html. But if I had to do it today, I'd use yarn workspaces, it's a better, more robust solution. – Tomer Mar 25 '20 at 19:34
  • @Tomer Thanks for this suggestion. You mentioned adding aliases, e.g. `@app1`. Where did you add those aliases and what purpose do they serve? – commander.trout Aug 17 '21 at 02:04
  • @Tomer where to use aliases ? – power-cut Nov 03 '21 at 18:14
  • @power-cut - the aliases are defined in vue.config.js, see this article: https://dev.to/alansolitar/webpack-aliases-in-vue-js-41hp – Tomer Nov 04 '21 at 12:36
  • @Tomer You share sources in `node_modules` and `shared` folders, but I suppose `vue-cli-service build` will anyway create two separate JS bundles for each app? So user's browser will have to download even the shared libraries separately for each app. – user14967413 May 22 '22 at 21:55
  • I tried the 'original post' recipe and got it working fairly easily, but only with a common `index.html` in the `.src` folder, wich needed editing to run either app1 or app2. Adding a separate `index.html` to each app folder resulted in an empty html when it ran, even though I changed `webRoot` in `launch.json` – quilkin Jan 24 '23 at 15:44
1

There will be a file level/source control solution to allow you to synchronise copies of the shared component in the two projects. If you're using Git, look at shared submodules.

There is strong potential here for a nightmare. You've described it so well I think you're secretly aware. Reusable components (reusable across projects) shouldn't have a dependency on a vuex store, which is application specific. I would look at putting the store calls in a project-specific wrapper component, then passing them to the shared component as props. Reusable components shouldn't have any interaction with their environment apart from props and events, according to me.

bbsimonbb
  • 27,056
  • 15
  • 80
  • 110
  • I don't really see a problem with the store as long as I make sure to name the store actions properly, since the shared component calls `this.$store.dispatch("someAction")` it will call the store that is in the context of the app it was called in. Moreover, I can even have shared modules that are added to the store using the `modules` property – Tomer Feb 19 '19 at 09:46
  • That's exactly the problem. You will need to *implicitly understand* that the store needs x action. Someone scanning your component code in 6 months will look at the props and events sections to know how to drive it. They will not scan every line looking for a call into the store. Someone perhaps modifying (renaming) the store action in one project might rename the call in the component, and break the other project. Creating components, your objective should be that you don't need to implicitly understand anything. – bbsimonbb Feb 19 '19 at 09:55
  • 1
    First of all, if I'm using modules, I define the actions on the shared module, so it won't be defined for each project. Secondly, what you are saying is correct when creating a component library, but this is not the case, I'm just looking for a way to make my life easier so I don't have to maintain the same code twice since a lot of it is practically the same. – Tomer Feb 19 '19 at 09:58
0

If you are using Vite (now recommended by vuejs.org) then it's easy to arrange this without having to learn new monorepo tools as discussed above. See my answer here

quilkin
  • 874
  • 11
  • 31