# Sharing components between projects

**URL:** <https://discourse.aurelia.io/t/sharing-components-between-projects/1743>\
**Category:** Help Requests\
**Created:** [October 11, 2018, 3:10pm UTC](https://discourse.aurelia.io/t/sharing-components-between-projects/1743 "2018-10-11T15:10:55Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![jdonzallaz](https://avatars.discourse-cdn.com/v4/letter/j/df705f/32.png) [@jdonzallaz](https://discourse.aurelia.io/u/jdonzallaz)\
**Post date:** [October 11, 2018, 3:10pm UTC](https://discourse.aurelia.io/t/sharing-components-between-projects/1743/1 "2018-10-11T15:10:55Z")

</div>

Hello,

Here is our current environment:

- 1 Visual Studio solution with several projects (Aurelia and .NET Core Web API)
- Aurelia projects with built-in bundler

We have already 2 “standalone” Aurelia app (A and B) running. Our goal is to create a portal/dashboard that will include the projects A and B.  
We tried to load the main component of project A as a route in the portal ©, without success.  
It looked like this: `{ ..., route: 'route/:a?/:b?', moduleId: '../../../ProjectA/src/resources/elements/main-component', ... }`.

Is there a way to accomplish this, while keeping those projects separated ?

If possible, the included project/component will use the authentication mechanism of the including project.

Do you have resources to share about sharing code (components, services, configuration) between different projects in the same repo ?

Edit: I would like to add that our ideal structure would look something like this:

- ProjectWebAPI
- ProjectPortal
- ProjectA
- ProjectB
- ProjectFramework - will hold shared service (http, auth, …) and components (navbar, sidebar, …)

Thanks for your help !

---

<div class="post-metadata">

**Author:** ![zewa666](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/zewa666/32/19_2.png) [@zewa666](https://discourse.aurelia.io/u/zewa666)\
**Post date:** [October 11, 2018, 8:42pm UTC](https://discourse.aurelia.io/t/sharing-components-between-projects/1743/2 "2018-10-11T20:42:10Z")

</div>

Yeah that should be doable with path mappings. Take a look at the fresh new cli docs [https://aurelia.io/docs/cli/cli-bundler/basics#path-mappings](https://aurelia.io/docs/cli/cli-bundler/basics#path-mappings)

---

<div class="post-metadata">

**Author:** ![huochunpeng](https://avatars.discourse-cdn.com/v4/letter/h/49beb7/32.png) [@huochunpeng](https://discourse.aurelia.io/u/huochunpeng)\
**Post date:** [October 11, 2018, 9:24pm UTC](https://discourse.aurelia.io/t/sharing-components-between-projects/1743/3 "2018-10-11T21:24:54Z")

</div>

I recommend to do the proper way, extract all your shared components/css to few aurelia plugins.  
Then you can easily load them up in any apps.

If you want an easy way to develop plugin, have a look of [https://github.com/aurelia-contrib/aurelia-getting-started/blob/master/guides/how-to-use-cli-to-develop-plugin.md](https://github.com/aurelia-contrib/aurelia-getting-started/blob/master/guides/how-to-use-cli-to-develop-plugin.md)

---

<div class="post-metadata">

**Author:** ![huochunpeng](https://avatars.discourse-cdn.com/v4/letter/h/49beb7/32.png) [@huochunpeng](https://discourse.aurelia.io/u/huochunpeng)\
**Post date:** [October 11, 2018, 9:34pm UTC](https://discourse.aurelia.io/t/sharing-components-between-projects/1743/4 "2018-10-11T21:34:25Z")

</div>

The path mapping itself is not enough @zewa666, you need to show him/her how you setup your transpile sources to catch all those foreign files.

---

<div class="post-metadata">

**Author:** ![davismj](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/davismj/32/267_2.png) [@davismj](https://discourse.aurelia.io/u/davismj)\
**Post date:** [October 12, 2018, 9:11am UTC](https://discourse.aurelia.io/t/sharing-components-between-projects/1743/5 "2018-10-12T09:11:29Z")

</div>

This is something I’ve architected for several applications already. As CP said, using plugins is the way to go. More specifically:

- ProjectFramework should be written as a plugin.
- ProjectA should be written as a plugin that depends on ProjectFramework.
- ProjectB should be written as a plugin that depends on ProjectFramework.
- ProjectPortal should be a standalone project.

Framework will need to be your connection between the plugins and the portal. A common use case for this is menus. Define an API in Framework for extending routes and menus. ProjectA and ProjectB will use that API to define their specific routes and menu items. Portal will read that API to register the routes and display the menu.

Something else to consider is the why. If you’re planning to deploy your application with various configurations for various customers, for example, then you’re going to need more than what you’re asking for here, or else you will end up forking Portal for each customer and reconfiguring it every time. If you want to create a straightforward API for quickly plugging new features and new applications, then this is the way to go.

---

<div class="post-metadata">

**Author:** ![timfish](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/timfish/32/1566_2.png) [@timfish](https://discourse.aurelia.io/u/timfish)\
**Post date:** [October 12, 2018, 1:15pm UTC](https://discourse.aurelia.io/t/sharing-components-between-projects/1743/6 "2018-10-12T13:15:00Z")

</div>

We’ve achieved something like this via private modules in a monorepository. Using Yarn workspaces, our private modules get symlinked in the root `node_modules` and then get bundled in any top level project that references them. This allows us to have an Electron, browser and server apps which all use shared code, but this could work for any combination of top level targets.

The whole lot gets built using the latest TypeScript build mode which compiles dependencies in the correct order.

What works and what doesn’t?

**The good**

- Forces isolation between modules. You’ll get compile errors if you try and import something across module boundaries without using the module syntax.
- Modules are compiled separately (we’ve used this to migrate our code-base to `strict` TypeScript one module at a time).
- Simple in the future to publish a module to public or private npm repository.
- Go-to-definition in vscode takes you to the correct source file, even in a module dependency.

**The bad**

- Modules are compiled separately. This is much slower than a single transpile/build.
- Wont work with JSPM as resolution is through `node_modules`.
- Some node dependencies still don’t work by default in a monorepo with hoisted dependencies. You can selectively [disable hoisting](https://yarnpkg.com/blog/2018/02/15/nohoist/) where it breaks things.

**Is all this complication required?**

Shared code between multiple apps is achievable from a single directory of files with a decent bundler config for each top level app/entry point. For example, Webpack should tree shake out all the unused code and you should be left with only the files required by your top level app. The major downside is that you (and team members) are now responsible for ensuring you properly isolate your modules.

---

<div class="post-metadata">

**Author:** ![jdonzallaz](https://avatars.discourse-cdn.com/v4/letter/j/df705f/32.png) [@jdonzallaz](https://discourse.aurelia.io/u/jdonzallaz)\
**Post date:** [October 21, 2018, 11:25pm UTC](https://discourse.aurelia.io/t/sharing-components-between-projects/1743/7 "2018-10-21T23:25:17Z")

</div>

Thanks for your answers. Sorry for not coming back earlier, I was busy making some tests.

@huochunpeng First I updated my project to the last CLI version. I followed the guide “how to use cli to develop plugin”.  
It seems to work pretty well. But I think we’ll have to set up a private repository solution like Verdaccio. It was already hard to test (had to use npm link).  
Plus I was not able to import static resources from plugin to main application (like font-awesome).

@davismj So since this PoC is working, I will follow your advice and change A, B and the framework as plugins. Your definition of the portal with several clients is exactly what we’re doing. Good point !

@timfish I tried with only typescript import without success. But I’ll definitely have a look at Yarn workspace. Perhaps a combination of aurelia plugins + Yarn workspaces is the best/easiest option.

Thanks for sharing your experiences and details !

---

<div class="post-metadata">

**Author:** ![huochunpeng](https://avatars.discourse-cdn.com/v4/letter/h/49beb7/32.png) [@huochunpeng](https://discourse.aurelia.io/u/huochunpeng)\
**Post date:** [October 22, 2018, 12:35am UTC](https://discourse.aurelia.io/t/sharing-components-between-projects/1743/8 "2018-10-22T00:35:07Z")

</div>

With cli bundle, you don’t need npm link to use local package, use explicit config.

```auto
{
  "name": "private-plugin",
  "path": "../../private-plugin"
}

```

The above example assumes your app and plugin repos are in sibling folders.

---

<div class="post-metadata">

**Author:** ![huochunpeng](https://avatars.discourse-cdn.com/v4/letter/h/49beb7/32.png) [@huochunpeng](https://discourse.aurelia.io/u/huochunpeng)\
**Post date:** [October 22, 2018, 12:39am UTC](https://discourse.aurelia.io/t/sharing-components-between-projects/1743/9 "2018-10-22T00:39:12Z")

</div>

With font-awesome, the plugin’s dependencies should able to bring font-awesome to your local app node\_modules folder. You can import it normally.  
If it’s not in local node\_modules folder, add it to app’s dependencies.

---

<div class="post-metadata">

**Author:** ![lvparkington](https://yyz1.discourse-cdn.com/flex027/user_avatar/discourse.aurelia.io/lvparkington/32/736_2.png) [@lvparkington](https://discourse.aurelia.io/u/lvparkington)\
**Post date:** [November 2, 2018, 2:07pm UTC](https://discourse.aurelia.io/t/sharing-components-between-projects/1743/10 "2018-11-02T14:07:09Z")

</div>

Or add a \<require\> tag in the html file(s) pointing to the font awesome files saved in the ClientApp directory tree such as \<require from="./…/…/…/resources/styling/fontawesome/css/all.css"\>\</require\>
