I'm working on a set of VSTS extensions. Each extension is its own little Node project with its own package.json
and its own node_modules
folder. The folder structure is as follows:
- MyExtension
- package.json // containing all dev-dependencies
- tslint.json
- Tasks
- tsconfig.json
- Common
- common.ts // containing functioanlity shared across tasks
- package.json // containing all runtime dependencies for all projects
- My1stTask
- package.json // containing all prod-dependencies
- task.ts // containing task implementation
- ...
- ...
- My6thTask
- package.json // containing all prod-dependencies
- task.ts // containing task implementation
The way VSTS build tasks work, is that they should be fully self-contained. I've fixed this so far by copying the contents of the Common
project into each task and then run tsc
to convert them all to JavaScript.
This isn't bad but requires constant copying of the contents of Common to get anything tested.
I tried using local file references, added a dependency in each task's package.json to file:../common
, which works at development time, but this doesn't result in the common module being part of the task after generating the extension.
My background isn't in Node develpment, but in C#. I've searched all over and haven't found a solution that works well with vsts-extensions.
npm pack
doesn't seem to work, as the extension expects all files to be there. package.json/bundleDependencies
looks promising but doesn't bundle the local file reference.///<reference path="../common/common.ts"/>
works lovely for editing but still can't run after building the extension.Is there a way I can make this work "seamlessly" without having to take on bower or grunt and simply get each MyXthTask to have a copy of the local common module in their node_modules
folder?
Packages on under the @types organization are published automatically from DefinitelyTyped using the types-publisher tool as per the docs. In addition, to there is another way to add types to your packages: In your package.json.
Build Mode for TypeScript Running tsc --build ( tsc -b for short) will do the following: Find all referenced projects. Detect if they are up-to-date. Build out-of-date projects in the correct order.
I tried @matt-mccutchen's approach, but unfortunately, I couldn't get that to work with the VSTS build tasks due to the fact that these tasks require commonjs
:
"compilerOptions": {
"module": "commonjs",
"target": "es6",
But I did find a solution that works for me.
In the Tasks
folder I've added a tsconfig.json
which defines my default settings and includes the files from the Common library:
{
"compileOnSave": true,
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"sourceMap": true,
"strict": false,
"strictNullChecks": false,
"removeComments": true
},
"files": [
"./Common/uuidv5.d.ts",
"./Common/Common.ts"
]
}
Then in each task I created a tsconfig.json
which sets the output folder to the current folder for that project and which inherits from the tsconfig.json
in the Tasks
folder:
{
"extends": "../tsconfig.json",
"compilerOptions": {
"outDir": "./",
"sourceRoot": "./"
},
"files": [
"InstallExtension.ts"
]
}
This results in:
- MyExtension
- package.json // containing all dev-dependencies
- tslint.json
- Tasks
- tsconfig.json // Including Common by default
- Common
- common.ts // containing functionality shared across tasks
- package.json // containing all runtime dependencies for Common
- tsconfig.json // containing build configuration for just the common files, inherits from ..\Task\tsconfig.json
- My1stTask
- package.json // containing all prod-dependencies for the task
- task.ts // containing task implementation
- tsconfig.json // containing build configuration for the task, inherits from ..\Task\tsconfig.json
- ...
- ...
- My6thTask
- package.json // containing all prod-dependencies
- task.ts // containing task implementation
- tsconfig.json // containing build configuration for the task, inherits from ..\Task\tsconfig.json
When compiling a task the following
- My6thTask
- Common
- Common.js // Compiled common
- My6thTask
- task.js // Compiled task
- package.json // containing all prod-dependencies
- task.ts // containing task implementation
- task.json // defining the task UI
- tsconfig.json // containing build configuration for the task
The only thing I had to add to task.ts
is the following:
///<reference path="../Common/Common.ts"/>
import * as common from "../Common/Common";
And to change the execution handler in the task.json to point to the new location:
"execution": {
"Node": {
"target": "InstallExtension/InstallExtension.js", // was: InstallExtension.js
"argumentFormat": ""
}
}
And all seems fine :D. Combined with using glob-exec
I've been able to reduce the build time to less than a minute when building clean:
"initdev:npm": "npm install & glob-exec --parallel --foreach \"Tasks/*/tsconfig.json\" -- \"cd {{file.dir}} && npm install\"",
"compile:tasks": "glob-exec \"Tasks/*/tsconfig.json\" -- \"tsc -b {{files.join(' ')}}\"",
"lint:tasks": "glob-exec --parallel --foreach \"Tasks/*/tsconfig.json\" -- \"tslint -p {{file}}\"",
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