Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
This article explains how Azure Pipelines works with JavaScript apps. Microsoft-hosted agents preinstall common JavaScript build, test, and deployment tools like npm, Node.js, Yarn, and Gulp without requiring you to set up any infrastructure. You can also configure self-hosted agents.
To quickly create a pipeline for JavaScript, see the JavaScript quickstart.
Node tool installers
To install Node.js and npm versions that aren't preinstalled, or to install the tools on self-hosted agents:
- For npm, run the
npm i -g npm@version-number
command in your pipeline. - For Node.js, add the Use Node.js ecosystem v1 (UseNode@1) task to your pipeline.
To install a specific Node.js version, add the following code to your azure-pipelines.yml file:
- task: UseNode@1
inputs:
version: '16.x' # replace with the version you need
Note
This task can require significant time updating to a newer minor version every time the pipeline runs. Microsoft-hosted agents are regularly updated, so use this task only to install specific Node versions that aren't preinstalled. To find out what Node.js and npm versions are preinstalled on Microsoft-hosted agents, see Software.
Use multiple node versions
You can use the Use Node.js ecosystem v1 task with a matrix
strategy to build and test your app on multiple versions of Node.js. For more information, see Multi-job configuration.
pool:
vmImage: 'ubuntu-latest'
strategy:
matrix:
node_16_x:
node_version: 16.x
node_13_x:
node_version: 18.x
steps:
- task: UseNode@1
inputs:
version: $(node_version)
- script: npm install
Dependency tool installation
If you have development dependency tools in your project package.json or package-lock.json file, install the tools and dependencies through npm. The project file defines the exact version of the tools, independent of other versions that exist on the build agent.
To install these tools on your build agent, use a script, the npm task, or a command-line task in your pipeline.
To use a script:
- script: npm install --only=dev
To use the npm task:
- task: Npm@1
inputs:
command: 'install'
Tools you install this way use the npm npx
package runner, which detects the tools in its PATH resolution. The following example calls the mocha
test runner, and uses the development dependency version rather than the version installed globally through npm install -g
.
- script: npx mocha
To install tools your project needs that aren't set as development dependencies in package.json, call npm install -g
from a script in your pipeline. The following example installs the latest version of the Angular CLI by using npm
. Other scripts in the pipeline can then use the Angular ng
commands.
- script: npm install -g @angular/cli
Note
On Microsoft-hosted Linux agents, preface the command with sudo
, like sudo npm install -g
.
These tool installation tasks run every time the pipeline runs, so be mindful of their impact on build times. If the overhead seriously impacts build performance, consider using self-hosted agents preconfigured with the tool versions you need.
Note
These tool installation tasks run every time the pipeline runs, so be mindful of their impact on build times.
Dependency package downloads
You can use Yarn or Azure Artifacts to download packages from the public npm registry or a private npm registry that you specify in an *.npmrc file. To specify an npm registry, add its URL to the *.npmrc file in your code repository.
Use npm
You can use npm to download build packages in your pipeline in the following ways:
- For the simplest way to download packages without authentication, directly run
npm install
. - To use an authenticated registry, add the npm task.
- To run
npm install
from inside task runners Gulp, Grunt, or Maven, use the npm authenticate task.
Note
If your npm feed uses authentication, you must create an npm service connection on the Services tab in Azure DevOps Project settings to manage its credentials.
To install npm packages directly, use the following script in azure-pipelines.yml. If your build agent doesn't need development dependencies, you can speed up build times by adding the --only=prod
option to npm install
.
- script: npm install --only=prod
To use a private registry specified in your *.npmrc file, add the Npm@1
task to azure-pipelines.yml.
- task: Npm@1
inputs:
customEndpoint: <Name of npm service connection>
To pass registry credentials to npm commands via task runners such as Gulp, add the npmAuthenticate@0
task to azure-pipelines.yml before you call the task runner.
- task: npmAuthenticate@0
inputs:
customEndpoint: <Name of npm service connection>
Note
Microsoft-hosted agents use a new machine with every build. Restoring dependencies can take a significant amount of time. To mitigate the issue, you can use Azure Artifacts or a self-hosted agent with the package cache.
If your builds occasionally fail because of connection issues when you restore packages from the npm registry, you can use Azure Artifacts with upstream sources to cache the packages. Azure Artifacts automatically uses the credentials of the pipeline, which are ordinarily derived from the Project Collection Build Service account.
Note
Restoring dependencies can take a significant amount of time. To mitigate the issue, you can use Azure Artifacts or a self-hosted agent with the package cache.
If your builds occasionally fail because of connection issues when you restore packages from the npm registry, you can use Azure Artifacts with upstream sources to cache the packages. Azure Artifacts automatically uses the credentials of the pipeline, which are ordinarily derived from the Project Collection Build Service account.
Use Yarn
Use a script to install Yarn for restoring dependencies. Yarn is preinstalled on some Microsoft-hosted agents. You can install and configure Yarn on self-hosted agents like any other tool.
- script: yarn install
You can also use the CLI or Bash task in your pipeline to invoke Yarn.
JavaScript compilers
JavaScript apps use compilers such as Babel and the TypeScript tsc
compiler to convert source code into versions usable by the Node.js runtime or in web browsers. If you have a script object set up in your project package.json file to run your compiler, you can invoke it in your pipeline.
- script: npm run compile
You can also call compilers directly from the pipeline by using a script. These commands run from the root of the cloned source code repository.
- script: tsc --target ES6 --strict true --project tsconfigs/production.json
You can use the npm task to build the code if your project package.json defines a compile script. If you don't define a compile script, you can use the Bash task to compile your code.
Unit testing
You can configure your pipelines to run your JavaScript tests so they produce results in the JUnit XML format. You can then publish the results using the Publish test results task.
If your test framework doesn't support JUnit output, add support through a partner reporting module such as mocha-junit-reporter. You can either update your test script to use the JUnit reporter, or pass those options into the task definition if the reporter supports command-line options.
The following table lists the most commonly used test runners and the reporters you can use to produce XML results:
Test runner | Reporters for XML reports |
---|---|
Mocha | mocha-junit-reporter cypress-multi-reporters |
Jasmine | jasmine-reporters |
Jest | jest-junit jest-junit-reporter |
Karma | karma-junit-reporter |
Ava | tap-xunit |
The following example uses the mocha-junit-reporter and invokes mocha test
directly by using a script. This script produces the JUnit XML output at the default ___location of ./test-results.xml.
- script: mocha test --reporter mocha-junit-reporter
If you defined a test
script in your project package.json file, you can invoke it by using npm test
.
- script: npm test
Publish test results
To publish test results, use the Publish test results task.
- task: PublishTestResults@2
condition: succeededOrFailed()
inputs:
testRunner: JUnit
testResultsFiles: '**/test-results.xml'
Publish code coverage results
If your test scripts run a code coverage tool such as Istanbul, add the Publish code coverage results task. You can then see coverage metrics in the build summary and download HTML reports for further analysis.
The task expects Cobertura or JaCoCo reporting output. Ensure that your code coverage tool runs with the necessary options to generate the right output, for example --report cobertura
.
The following example uses the Istanbul command-line interface nyc along with mocha-junit-reporter, and invokes npm test
.
- script: |
nyc --reporter=cobertura --reporter=html \
npm test -- --reporter mocha-junit-reporter --reporter-options mochaFile=./test-results.xml
displayName: 'Build code coverage report'
- task: PublishCodeCoverageResults@2
inputs:
summaryFileLocation: '$(System.DefaultWorkingDirectory)/**/*coverage.xml'
End-to-end browser testing
Your pipeline can use tools like Protractor or Karma to run tests in headless browsers, and then publish test results. To configure browser testing and publish results, follow these steps:
- Install a headless browser testing driver such as headless Chrome or Firefox, or a browser-mocking tool such as PhantomJS, on the build agent.
- Configure your test framework to use your headless browser or driver option according to the tool's documentation.
- Configure your test framework to output JUnit-formatted test results, usually with a reporter plug-in or configuration.
- Add a script or CLI task to start the headless browser instances.
- Run the end-to-end tests in the pipeline stages along with your unit tests.
- Publish the results along with your unit tests by using the same Publish test results task.
Packaging and delivery
After you build and test your app, you can:
- Upload the build output to Azure Pipelines.
- Create and publish an npm or Maven package.
- Package the build output into a ZIP archive for deployment to a web application.
Publish files to Azure Pipelines
To upload the entire working directory, add the Publish build artifacts task to your azure-pipelines.yml file.
- task: PublishBuildArtifacts@1
inputs:
PathtoPublish: '$(System.DefaultWorkingDirectory)'
To upload a subset of files, first copy the necessary files from the working directory to a staging directory with the Copy files task, and then use the Publish build artifacts task.
- task: CopyFiles@2
inputs:
SourceFolder: '$(System.DefaultWorkingDirectory)'
Contents: |
**\*.js
package.json
TargetFolder: '$(Build.ArtifactStagingDirectory)'
- task: PublishBuildArtifacts@1
Publish a module to an npm registry
If your project's output is an npm
module for other projects to use and isn't a web application, use the npm task to publish the module to a local registry or to the public npm registry. Provide a unique name/version combination each time you publish.
The following example uses the script to publish to the public npm registry. The example assumes that you manage version information such as npm version through a package.json file in version control.
- script: npm publish
The following example publishes to a custom registry defined in your repo's *.npmrc file. Set up an npm service connection to inject authentication credentials into the connection as the build runs.
- task: Npm@1
inputs:
command: publish
publishRegistry: useExternalRegistry
publishEndpoint: https://my.npmregistry.com
The following example publishes the module to an Azure DevOps Services package management feed.
- task: Npm@1
inputs:
command: publish
publishRegistry: useFeed
publishFeed: https://my.npmregistry.com
For more information about versioning and publishing npm packages, see Publish npm packages and How can I version my npm packages as part of the build process.
Package and deploy a web app
You can package applications to bundle all modules with intermediate outputs and dependencies into static assets ready for deployment. Add a pipeline stage after compilation and testing to run a tool like webpack or the Angular CLI ng build.
The following example calls webpack
. For this process to work, make sure webpack
is configured as a development dependency in your package.json project file. This script runs webpack
with the default configuration, unless you have a webpack.config.js file in the root folder of your project.
- script: webpack
The following example uses npm run build
to call the build
script object defined in the project package.json file. Using the script object in your project moves the build logic into the source code and out of the pipeline.
- script: npm run build
You can also use the CLI or Bash task in your pipeline to invoke your packaging tool, such as webpack
or Angular's ng build
.
To create a *.zip file archive that's ready to publish to a web app, use the Archive files task.
- task: ArchiveFiles@2
inputs:
rootFolderOrFile: '$(System.DefaultWorkingDirectory)'
includeRootFolder: false
To publish this archive to a web app, see Deploy to Azure App Service by using Azure Pipelines.
JavaScript frameworks
You can install packages in your pipeline to support various JavaScript frameworks.
Angular
For Angular apps, you can run Angular-specific commands such as ng test
, ng build
, and ng e2e
. To use Angular CLI commands in your pipeline, install the angular/cli npm package on the build agent.
- script: |
npm install -g @angular/cli
npm install
ng build --prod
Note
On Microsoft-hosted Linux agents, preface the command with sudo
, like sudo npm install -g
.
For tests in your pipeline that require a browser to run, such as running Karma with the ng test
command, use a headless browser instead of a standard browser. In the Angular starter app:
- Change the
browsers
entry in your karma.conf.js project file frombrowsers: ['Chrome']
tobrowsers: ['ChromeHeadless']
. - Change the
singleRun
entry in your karma.conf.js project file fromfalse
totrue
. This change helps ensure that the Karma process stops after it runs.
React and Vue
All the dependencies for React and Vue apps are captured in your package.json file. Your azure-pipelines.yml file contains the standard npm
scripts.
- script: |
npm install
displayName: 'npm install'
- script: |
npm run build
displayName: 'npm build'
The build files are in a new folder, dist for Vue or build for React. The following example builds an artifact, www
, that's ready for release. The pipeline uses the Use Node.js, Copy file, and Publish build artifacts tasks.
trigger:
- main
pool:
vmImage: 'ubuntu-latest'
steps:
- task: UseNode@1
inputs:
version: '16.x'
displayName: 'Install Node.js'
- script: npm install
displayName: 'npm install'
- script: npm run build
displayName: 'npm build'
- task: CopyFiles@2
inputs:
Contents: 'build/**' # Pull the build directory (React)
TargetFolder: '$(Build.ArtifactStagingDirectory)'
- task: PublishBuildArtifacts@1
inputs:
PathtoPublish: $(Build.ArtifactStagingDirectory) # dist or build files
ArtifactName: 'www' # output artifact named www
To release the app, point your release task to the dist
or build
artifact and use the Azure Web App task.
Webpack
You can use a webpack configuration file to specify a compiler such as Babel or TypeScript, to transpile JavaScript XML (JSX) or TypeScript to plain JavaScript, and to bundle your app.
- script: |
npm install webpack webpack-cli --save-dev
npx webpack --config webpack.config.js
Build task runners
It's common to use Gulp or Grunt as task runners to build and test JavaScript apps.
Gulp
Gulp is preinstalled on Microsoft-hosted agents.
You can run the gulp
command in the YAML pipeline file.
- script: gulp # add any needed options
If the steps in your gulpfile.js file require authentication with an npm registry, add the npm authenticate task.
- task: npmAuthenticate@0
inputs:
customEndpoint: <Name of npm service connection>
- script: gulp
To publish JUnit or xUnit test results to the server, add the Publish test results task.
- task: PublishTestResults@2
inputs:
testResultsFiles: '**/TEST-RESULTS.xml'
testRunTitle: 'Test results for JavaScript using gulp'
To publish code coverage results to the server, add the Publish code coverage results task. You can find coverage metrics in the build summary, and you can download HTML reports for further analysis.
- task: PublishCodeCoverageResults@1
inputs:
codeCoverageTool: Cobertura
summaryFileLocation: '$(System.DefaultWorkingDirectory)/**/*coverage.xml'
reportDirectory: '$(System.DefaultWorkingDirectory)/**/coverage'
Grunt
Grunt is preinstalled on Microsoft-hosted agents.
You can run the grunt
command in the YAML file.
- script: grunt # add any needed options
If the steps in your Gruntfile.js file require authentication with an npm registry, add the npm authenticate task.
- task: npmAuthenticate@0
inputs:
customEndpoint: <Name of npm service connection>
- script: grunt
Troubleshooting
If you can build your project on your development machine but can't build it in Azure Pipelines, explore the following potential causes and corrective actions.
Check that the versions of Node.js and the task runner on your development machine match the ones on the agent.
You can include command-line scripts such as
node --version
in your pipeline to check the versions installed on the agent. Either use theUse Node.js
task to install the same version on the agent, or runnpm install
commands to update the tool versions.If your builds fail intermittently while you restore packages, either the npm registry has issues, or there are networking problems between the Azure data center and the registry. Explore whether using Azure Artifacts with an npm registry as an upstream source improves the reliability of your builds.
If you're using
nvm
to manage different versions of Node.js, consider switching to the Use Node.js (UseNode@1) task instead.nvm
is installed for historical reasons on the macOS image.nvm
manages multiple Node.js versions by adding shell aliases and alteringPATH
, which interacts poorly with the way Azure Pipelines runs each task in a new process. For more information, see Pipeline runs.The
Use Node.js
task handles this model correctly. However, if your work requires usingnvm
, you can add the following script to the beginning of each pipeline:steps: - bash: | NODE_VERSION=16 # or your preferred version npm config delete prefix # avoid a warning . ${NVM_DIR}/nvm.sh nvm use ${NODE_VERSION} nvm alias default ${NODE_VERSION} VERSION_PATH="$(nvm_version_path ${NODE_VERSION})" echo "##vso[task.prependPath]$VERSION_PATH"
Then,
node
and other command-line tools work for the rest of the pipeline job. In each step where you use thenvm
command, start the script with the following code:- bash: | . ${NVM_DIR}/nvm.sh nvm <command>
FAQ
How do I fix a pipeline failure with the message 'FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory'?
This failure type occurs when the Node.js package exceeds the memory usage limit. To resolve the issue, add a variable like NODE_OPTIONS
and assign it a value of --max_old_space_size=16384
.
How can I version my npm packages as part of the build process?
One option is to use a combination of version control and npm version. At the end of a pipeline run, you can update your repo with the new version. The following YAML pipeline has a GitHub repo, and the package deploys to npmjs. The build fails if there's a mismatch between the package version on npmjs and the package.json file.
variables:
MAP_NPMTOKEN: $(NPMTOKEN) # Mapping secret var
trigger:
- none
pool:
vmImage: 'ubuntu-latest'
steps: # Checking out connected repo
- checkout: self
persistCredentials: true
clean: true
- task: npmAuthenticate@0
inputs:
workingFile: .npmrc
customEndpoint: 'my-npm-connection'
- task: UseNode@1
inputs:
version: '16.x'
displayName: 'Install Node.js'
- script: |
npm install
displayName: 'npm install'
- script: |
npm pack
displayName: 'Package for release'
- bash: | # Grab the package version
v=`node -p "const p = require('./package.json'); p.version;"`
echo "##vso[task.setvariable variable=packageVersion]$v"
- task: CopyFiles@2
inputs:
contents: '*.tgz'
targetFolder: $(Build.ArtifactStagingDirectory)/npm
displayName: 'Copy archives to artifacts staging directory'
- task: CopyFiles@2
inputs:
sourceFolder: '$(Build.SourcesDirectory)'
contents: 'package.json'
targetFolder: $(Build.ArtifactStagingDirectory)/npm
displayName: 'Copy package.json'
- task: PublishBuildArtifacts@1
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)/npm'
artifactName: npm
displayName: 'Publish npm artifact'
- script: | # Config can be set in .npmrc
npm config set //registry.npmjs.org/:_authToken=$(MAP_NPMTOKEN)
npm config set scope "@myscope"
# npm config list
# npm --version
npm version patch --force
npm publish --access public
- task: CmdLine@2 # Push changes to GitHub (substitute your repo)
inputs:
script: |
git config --global user.email "username@contoso.com"
git config --global user.name "Azure Pipeline"
git add package.json
git commit -a -m "Test Commit from Azure DevOps"
git push -u origin HEAD:main
Related content
- For more information about Azure Artifacts and the Package Management service, see Package Management in Azure Artifacts.
- For more information about tasks, see Build, release, and test tasks.