You might have figured – I’m a VSCode fanboy. One of many. You might remember the session I did on NAVTechDays 2017 (Rock ‘n Roll with VSCode), where I dove quite a bit into the possibilities this great tool comes with. But I didn’t talk about the concept of “Multi-root Workspaces”: an ability of VSCode for you to work on multiple “projects” at the same time, in one environment.
2 years later, last NAVTechDays, I talked about Dependencies quite a lot, and when you think of it – in terms of dependencies in AL for Business Central, these “Multi-root Workspaces” might make a lot of sense, because when you have all these apps, you might have to work on multiple apps at the same time.
Even more, in that same video, you’ll see that I ALWAYS have at least 2 apps: an app, and its test-app. So in terms of “Test Driven Development” (a methodology I believe is indispensable), you will always have an app, and a dependent app, and you will always work on both apps at the same time. So – “Multi Root” to the rescue!
Well, the concept of “multi-root workspaces” is actually most simply explained by: opening multiple projects (workspaces) at the same time, to be able to work on multiple pieces of software at the same time. Or in terms of Business Central: to work (compile, publish, develop, …) on multiple apps at the same time.
The concept is quite well explained on the docs-page for VSCode: https://code.visualstudio.com/docs/editor/multi-root-workspaces
The one downside of this concept is that not every VSCode extension might be ready in a Multi-root environment. In fact, it took a while to get my own extension (the CRS AL Language Extension) ready for Multi-root workspaces (and there still might be issues with it ;-)).
Same for Microsoft’s AL Language Extension. It took a while – but just imagine:
- When you’re working on extension A, from which Extension B is dependent – Extension B will recognize the symbols of Ext A without even having to create (compile) an app file – just because Ext B is in your Multi Root Workspace
- When you’re debugging, you’re able to go to definition into al-files of other apps you’re debugging – not just the only-one-level-dal-files. Just because you have the dependent app in your workspace.
- Whenever you compile a main app, the symbol files of the dependent apps are updated with the new version of the main app. Just because it’s in your multi-root workspace.
All this is already possible!
And that’s what a real “Multi-root” experience can give you – and why I think we should always look into this. It makes all the sense in the world – in a world with “lots” of apps and dependencies, to work on them simultaneously. And I’m sure – if you’re not yet doing it – it can speed up your development process even more!
May be a few screenshots that can show you how it could look like.
In this case, I’m actually working on 7 apps at the same time, with all of them having a test-app as well (which we use for unit-testing). The last app is the integration-test-app.
How does it determine what app I’m working in?
Well, simply by the active editor. If I would want to compile and publish the BASE-App, I would open one of the files of that app, and simply press F5.
Symbols constantly updated over all workspaces
In my case, the BASE App is a library-app for all other apps. And if I would simply start coding in that BASE-App, like this useless codeunit:
I would – without even compiling my app – be able to code against this in any app that is dependent from that BASE-App:
Basically meaning: I can code against all apps at the same time, without even downloading/updating symbols, or compiling or publishing.
Even, when you hit compile, you’ll notice that the symbol files in the .alpackages-folder are updated for all apps that depend from the app that you’re compiling. Very cool!
Can I control this a bit?
Well – you do have the “dependencyPublishingOption” in the launch.json, which has 3 options:
- Default: set dependency publishing will be applied
- Ignore: Only the current project is published, dependencies are ignored.
- Strict: Publishing will fail if the project has apps that not part of the workspace and depend on it
I like the default setting – something it takes a little longer to include all dependencies in the compile – but at least you’re checking all dependencies .. So that must be good ;-). But, in some cases – especially in case of big apps with many objects – you might want to avoid unnecessary recompiles of dependent apps.. .
Does this mean everything needs to be in one (Git) repository?
No! VSCode is smart enough to handle multiple workspaces at the same time. In case of the screenshot above – and as mentioned in a recent webcast I did about handling dependencies in DevOps – all my apps are in separate repos, together with their Test-apps. So in case of the screenshot, it would be a collection of about 8 GIT repositories. When you switch to the “Source Control” window, VSCode clearly shows all states of the repositories, like you see here in the screenshot:
You can simply see when repos need attention (new/modified/delete files), what branches, and what the synchronization state is. From this window, you can obviously also change branches, sync, and so on.. .
There is more …
And I have more for you. To make working in multiple workspaces more easy, I’m working on a set of scripts, which you find on my PowerShell repository: https://github.com/waldo1001/Cloud.Ready.Software.PowerShell
I will maintain a set of scripts in the folder ./PSScripts/NAV Extensions v2/MultiRootWorkspaces/ . Today, I have foreseen:
- LaunchJson_CopyToAll.ps1: If you change docker image or whatever – this script will simply copy one launch.json to all other workspaces so that you will easily publish other dependent apps to the same sandbox
- Symbol_Cleanup.ps1: This script removes all symbol files – just imagine when you want to publish against another version (localization, insider, ..), you can simply cleanupt all files and even invoke the next script, which will …
- Symbol_Download.ps1: This script will download as many symbols as possible for all workspaces that are available in your multiroot workspace.
I’m also working on a “CompileAll” script – would be nice to have one script that figures our the dependency tree (I already got that one), and invoke start compiling all the apps – and – may be – if possible – even starts publishing them to the server instance ;-). Let’s see where we end up with that one ;-).
There might be issues with the scripts – they are brand new 😉 – but please, use, abuse .. and contribute ;-).
Enjoy going Multi-root!
I tried to use multi workspaces because I have different version of NAV/BC and i have to disable al extension nav in bc and disable al extension bc for nav => it works.
But when I have tried to work with two extensions that are independant (with no dependencies). the symbol are not recognized by one of both.
So, my question , is it mandatory to have dependencies between extensions to work in a workspace ?
NO, it’s not mandatory. When there are no dependencies, there is no reason for any symbol to be craeted in other workspaces while compiling or such …
ok. but the symbol are not recognized in the same workspace for one of the apps included in, do you know why ?
No idea – I’d have to see it 🙁
create a new issue on GitHub with screenshots and enough information .. and if possible a zip-file with code – and I’ll try to have a look!
ok possible to show you 🙂 ?
Done : thanks.
In my testing it seemed to work better when the al.packageCachePath was set to a central place.
Could be a good starting place.
Hi Waldo, First of thank you for this detailed post.
In a previous post you talked about the CRS extension and that you had trouble with mult-root projects rename with git, has that issue been remedied since then? I do not see mention of it here, this would go a long way for refactoring very large applications. 12 apps and counting with a strict dependency tree, a single object id or name could result in 6 or 7 apps needing updated, which is time consuming to say the least.
No, still same problem.
but – if you want to rename – you can also NOT renamewithgit, and just stage before you would commit. While staging, git is going to compare files, and “rename” the files rather than “delete and create”.. .
Please help convince Microsoft to enable it in their tools:
Hi Eric, after redesign our extensions to the app/test folder structure, I’m having some issues with todo-tree not taking up the proper settings from each app folder? I’ve removed any todo-tree settings from the .code-workspace file and moved it back to each app folder (settings.json file) However, todo-tree seems not to find any settings in the individual folder. Do you have similar issues, any clue?
Well, I don’t use settings, so I don’t know – I expect it to be the same.. .
I noticed that even intellisense doesn’t work for settings on single-workspace-level (in multiroot). I don’t know why that is – I guess you’ll have to take it up with the people from todotree.
As I mentioned in my post – not all extensions are multiroot-ready :(.