I've built my project starting form the angular universal template found here:
universal-starter
I am trying to deploy the ssr build as azure web app. My code is on VSTS.
On my local machine I can run the following:
npm install
npm run build:ssr. This produces the dist folder.
I can then copy the dist folder somewhere else and run with the command below
node server.js
The app starts on port 4000 on local machine.
So following the steps above, I've created a build process on my VSTS with the following tasks:
An npm task that runs npm install
An npm task that run npm run build:ssr
An azure app service deploy task with the following configurations:
Package Folder: dist/
web.config parameters: -Handler iisnode -NodeStartFile server.js -appType node
Above process runs successfully, but when I navigate to https://my-site-name.azurewebsites.net/ the site cannot be reached.
How can I successfully deploy Angular 5 SSR on Azure?
UPDATE:
Since this NodeJS-EmptySiteTemplate runs on azure without error, I've done the following changes as per that project:
That server is listening on process.env.PORT | 8080
There was a web.config file there that I was missing. I placed the same web-config file in the wwwroot.
But not I am getting: "The page cannot be displayed because an internal server error has occurred."
After spending many hours on this, I am going to expand on Starians answer. Although it did eventually help me get azure working, there were bits of information missing or incorrect.
So, I am going to try to do a step by step walk though.
The first thing to note, is that I do not change any file to get this to work.
If you change webpack.server.config.js then when you do a local build:ssr it will create server.js in your root application folder, which is undesirable.
So, if you are using the azure visual designer, you can follow these steps:
First, connect to your repository and setup the branch you wish to use
Add the Node Tool Installer task and set it to use the current version of node
Add an npm task and set the Command to custom; Set the Command and arguments to install #angular/cli -g (name it "npm install angular cli")
Add another npm task but keep it on install (name it something like "npm install packages")
Add a Command Line task and set the script to npm run build:ssr (name it "build the project")
Add a Copy files task, set the Source folder to $(Build.SourcesDirectory)/dist, the Contents to ** and the Target folder to $(Build.ArtifactStagingDirectory)/app/dist (name it something like "Copy dist files to staging"
Add another Copy files task, set the Source folder to $(Build.ArtifactStagingDirectory)/app/dist, the Contents to server.js and the Target folder to $(Build.ArtifactStagingDirectory)/app (name this something like "Copy server.js to the root")
Then add a Delete Files task, set the Source folder to $(Build.ArtifactStagingDirectory)/app/dist and the Contents to server.js (name this something like "Delete the dist/server.js"
Finally, add an Azure App Service Deploy task, set the Package or folder to $(Build.ArtifactStagingDirectory)/app
Find the File Transforms & Variable Substituion Options, make sure Generate Web.config is selected and add these Web.config parameters: -Handler iisnode -NodeStartFile server.js -appType node
If you follow that guide properly, you should end up with a folder structure similar to:
web.config
server.js
dist
and the dist folder should contain two more folders (browser and server).
If that is the case (and it should be) you will have a working Angular Universal application.
For those that would like it, here is the yml:
queue:
name: Hosted VS2017
demands: npm
steps:
- task: NodeTool#0
displayName: 'Use Node 8.x'
inputs:
versionSpec: 8.x
- task: Npm#1
displayName: 'npm install angular cli'
inputs:
command: custom
verbose: false
customCommand: 'install #angular/cli -g'
- task: Npm#1
displayName: 'npm install packages'
inputs:
verbose: false
- script: 'npm run build:ssr'
displayName: 'build the project'
- task: CopyFiles#2
displayName: 'Copy dist files to staging'
inputs:
SourceFolder: '$(Build.SourcesDirectory)/dist'
TargetFolder: '$(Build.ArtifactStagingDirectory)/app/dist'
- task: CopyFiles#2
displayName: 'Copy server.js to the root'
inputs:
SourceFolder: '$(Build.ArtifactStagingDirectory)/app/dist'
Contents: server.js
TargetFolder: '$(Build.ArtifactStagingDirectory)/app'
- task: DeleteFiles#1
displayName: 'Delete the dist/server.js'
inputs:
SourceFolder: '$(Build.ArtifactStagingDirectory)/app/dist'
Contents: server.js
- task: AzureRmWebAppDeployment#3
displayName: 'Azure App Service Deploy: website'
inputs:
azureSubscription: 'Subscription 1'
WebAppName: website
DeployToSlotFlag: true
ResourceGroupName: Temp
SlotName: master
Package: '$(Build.ArtifactStagingDirectory)/app'
GenerateWebConfig: true
WebConfigParameters: '-Handler iisnode -NodeStartFile server.js -appType node'
UseWebDeploy: true
RemoveAdditionalFilesFlag: true
I hope this helps someone else :)
I recommend that you are using current directory as working folder instead of add additional dist folder (const DIST_FOLDER = join(process.cwd(), 'dist');).
You can enable diagnostics logs of that app service and check the detail logs, it still looks for index view in D:\home\site\wwwroot\dist\dist\browser, so it is incorrect and will throw 500 error.
BTW: the port is 80 (process.env.PORT) instead of 4000.
Update:
The server.ts requires module files in dist folder, so just change DIST_FOLDER is not working. The simple way is putting server.js out of dist folder (Do not modify server.ts).
Simple steps:
Open webpack.server.config.js
Replace path: path.join(__dirname, 'dist') to path:__dirname
NPM Install task
NPM Custom task (run build:ssr)
Copy Files task (Source Folder: $(Build.SourcesDirectory)/dist; Contents: **; Target Folder: $(Build.ArtifactStagingDirectory)/app/dist)
Copy Files task (Source Folder: $(Build.SourcesDirectory); Contents: server.js prerender.js (one per a line)
Azure App Service Deploy task (Package or folder: $(Build.ArtifactStagingDirectory)/app; Webconfig parameters: -Handler iisnode -NodeStartFile server.js -appType node)
Related
I've got a simple Vue SPA that builds and can be served without problem locally, but when I try and build and deploy via GitHub Actions to an Azure App Service, it just results in the ':( Application Error' page when launching.
Below is the pretty much default workflow .yml, the app service configuration, and the error log from trying to build the app.
I assume the files are built from the /dist folder at /home/site/wwwroot, where node_modules are installed and package.json is generated.. but it doesn't seem like it is (there are no files when checking wwwroot, so build failed?)
Any help would be appreciated, I've been stuck on this for a whole day and will happily provide more info. I've also deployed the NodeJS backend to an app service without too much hassle, so I'm familiar with the process -- just can't get this frontend up!
name: Build and deploy Node.js app to Azure Web App - shelf-library
on:
push:
branches:
- main
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout#v2
- name: Set up Node.js version
uses: actions/setup-node#v1
with:
node-version: '16.x'
- name: npm install, build, and test
run: |
npm install
npm run build --if-present
- name: Upload artifact for deployment job
uses: actions/upload-artifact#v2
with:
name: node-app
path: dist/
deploy:
runs-on: ubuntu-latest
needs: build
environment:
name: 'Production'
url: ${{ steps.deploy-to-webapp.outputs.webapp-url }}
steps:
- name: Download artifact from build job
uses: actions/download-artifact#v2
with:
name: node-app
- name: 'Deploy to Azure Web App'
id: deploy-to-webapp
uses: azure/webapps-deploy#v2
with:
app-name: 'shelf-library'
slot-name: 'Production'
publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_11D7C84BF0CE47B68181C49B9ED47D19 }}
package: .
Check the below steps to create VueJS and deploy to Azure App Service using Git Hub Actions.
Thanks #Anthony Salemo for the clear steps.
In Command prompt, run the below command to create a Vue App.
vue create myvueapp
Navigate to the root directory of the application cd myvueapp and run
yarn serve
or
npm run serve
Run npm run build command for production build.dist folder will be created.
Push the application to GitHub Repository.
You can check the code available in my GitHub Repository.
My GitHub folder structure
Create an Azure App service
Navigate to your App Service =>Deployment Center and select the code repo from your GitHub.
Initially I got the below content page when I tried to access the App.
Add the Startup Command in Configuration => General Settings.
pm2 serve /home/site/wwwroot/dist --spa --no-daemon
Initially even I got the same Application Error.
In Git Hub I can see the build and deploy action is not yet completed.
Wait for the build to deploy successfully.
My deployed folder structure in KUDU Console
Now Iam able to access the Application without any issues.
I saw you are running your stages with different agents, so I suppose that your issue could be resulted from that the configuration in the build stage agent could not be inherited into the deploy stage agent.
So you could test to add the npm task to install the vue-cli-service module in your deploy agent again.
==========================================================
Updated on 12/22
I suppose that in deploy stage, you could add the npm and node installation with below.
- name: Set up Node.js version
uses: actions/setup-node#v1
with:
node-version: '16.x'
- name: npm install, build, and test
run: |
npm install
npm run build --if-present
- name: npm install, build, and test
run: |
npm install -g #vue/cli#latest
npm i -g #vue/cli-service-global
echo '<template><h1>Hello!</h1></template>' > App.vue
vue serve
I have deployed my Next.js project to the Azure App service that needs to include "node_modules" to run the production ("npm start").
But.. I found that the "node_modules" size is so big (354,3 MB on disk).
And then I saw that we could use the "Output File Tracing" feature to reduce the size of deployments drastically.
So how can I use that feature? I think that will affect my Azure Pipeline and Release
Below are the steps of solution how I deploy my Next.js project to Azure App Service with the "Output File Tracing" feature.
Project Setup
1. Your Next.js version should be version 12.2.x or higher. So upgrade your Next.js first to the required version.
2. Add output: "standalone in 📄 next-config.js
// example
const nextConfig = {
output: "standalone",
};
module.exports = nextConfig;
3. And you can try to build it. npm run build
4. There will be a folder called 📁 standalone inside 📁.next
5. Inside the 📁 standalone, there is a 📄 server.js.
6. Open your cmd/terminal and then change the directory to 📁 standalone with cd .next/standalone. You can run the 📄 server.js using node. Example: node server.js. And then it will be run in port 3000. You can open it in the browser and then access localhost:3000.
7. There will be some errors of "some files are missing" (404). You need to copy the 📁 static inside 📁 .next to /.next/standalone/.next/ and re-run the node server.js.
7.1. You can update your script to copy it automatically when you run the build script. First install cpy-cli as dev-dependencies npm i cpy-cli -D.
7.2. In 📄 package.json. Update build script
"build": "next build && ./node_modules/.bin/cpy '.next/static/**' '.next/standalone/.next/static/'"
7.3. Try to build again and then the 📁 static will be copied automatically.
Pipelines
Archive only 📁 standalone.
azure-pipelines.yml
# Node.js
# Build a general Node.js project with npm.
# Add steps that analyze code, save build artifacts, deploy, and more:
# https://learn.microsoft.com/azure/devops/pipelines/languages/javascript
trigger:
- main
pool:
vmImage: ubuntu-latest
steps:
- task: NodeTool#0
inputs:
versionSpec: '18.x'
displayName: 'Install Node.js'
- script: |
npm install
npm run build
displayName: 'npm install and build'
- task: ArchiveFiles#2
inputs:
rootFolderOrFile: "./.next/standalone/"
includeRootFolder: false
archiveType: "zip"
archiveFile: "$(Build.ArtifactStagingDirectory)/$(Build.BuildId).zip"
replaceExistingArchive: true
- task: PublishBuildArtifacts#1
inputs:
PathtoPublish: "$(Build.ArtifactStagingDirectory)"
ArtifactName: "drop"
publishLocation: "Container"
Release
Done 🌟
If you facing a problem like the public content is missing, you need to copy your 📁 public to 📁 standalone. You can do it manually or update your build script to be like this:
package.json
"build": "next build && ./node_modules/.bin/cpy '.next/static/**' '.next/standalone/.next/static/' && ./node_modules/.bin/cpy './public/**' '.next/standalone/public/'",
I'm trying to deploy a react web app. Here is my current yaml file. I've been following this tutorial.
trigger:
- master
pool:
vmImage: 'ubuntu-latest'
variables:
azureSubscription: <myServiceConnection>
appName: <myAppName>
steps:
- task: NodeTool#0
inputs:
versionSpec: '10.x'
displayName: 'Install Node.js'
#so this calls the build object in package.json. Theoretically creates a /build/ directory
- script: |
npm install
npm run build
displayName: 'npm install and build'
#this should copy contents of build into artifactstagingdirectory.
- 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
- task: AzureWebApp#1
inputs:
azureSubscription: <myServiceConnection>
appName: <myAppName>
appType: webAppLinux
package: $(Build.ArtifactStagingDirectory)/**/www/build
customWebConfig: '-handler iisnode -NodeStartFile server.js -appType node'
Basically, the issue is that I dont understand where the PublishBuildArtifact task publishes the files, and so I don't know where to point the package of AzureWebApp to.
So I turned on system.debug and I got the following information
npm install build uses the following directory: /home/vsts/work/1/s
copy files copies the build folder over. So it goes /home/vsts/work/1/s/build to /home/vsts/work/1/a/build. So this means artifactstagingdirectory is /home/vsts/work/1/a
Publish Build artifacts takes the artifactstagingdirectory and publishes it to some folder www/build. The following output is provided: Upload '/home/vsts/work/1/a' to file container: '#/8995596/www'
The current AzureWebApp task is looking in /home/vsts/work/1/a/**/www/build
So I think it should be the right directory. However, it is not providing the whole path in step 3. So it looks like I'm wrong. Where is this www folder being created?
Also since it doesn't seem like building/publishing the react app will create a zip file, do I just point it to the build folder or the www folder?
try
**/wwwroot/
instead of **/www/
Check following blog from Microsoft with deployment details outlined.
https://learn.microsoft.com/en-us/azure/app-service/faq-deployment
I am having trouble understanding and getting the build/release pipelines setup for deploying a NestJS application to Azure DevOps (ADO).
I am deploying to a Linux Web App hosted in Azure.
As far as I understand, if I run the app locally using something like npm run start, it creates a dist folder under my root project directory.
So, when writing the YAML for the build and deployment. My thought process is to:
Run an NPM update.
Run npm run build to build the application and generate the dist folder.
Copy the contents of the application (or just the dist folder?) into the target folder (/home/site/wwwroot)
Run npm run start:prod to start the server.
Here is my YAML so far:
trigger:
- master
pool:
vmImage: 'ubuntu-latest'
steps:
- task: UseNode#1
inputs:
version: '14.x'
checkLatest: true
- task: Npm#0
displayName: Run NPM Update for NestJS
inputs:
cwd: '$(Build.SourcesDirectory)/ProjectName'
command: update
- task: Npm#0
displayName: Build NestJS
inputs:
cwd: '$(Build.SourcesDirectory)/ProjectName'
command: run
arguments: "build"
- task: CopyFiles#2
inputs:
Contents: 'dist/**'
TargetFolder: '$(Build.ArtifactStagingDirectory)'
The issue is after the build process completes, I do not see a dist folder in /home/site/wwwroot/ProjectName. Can someone help me out with what I am missing?
Also, a side noob-y question about Azure DevOps, what does $(Build.SourcesDirectory) and $(Build.ArtifactStagingDirectory) refer to and how and where are those environment variables set?
To deploy your app to the hosted in Azure. You need to use Azure App Service Deploy task or Azure Web App task.
Azure devops is the tool to build and deploy your app to your server(eg. the Linux Web App on Azure), it is not for hosting your app.
$(Build.ArtifactStagingDirectory) refer to the folder of the agent machine which runs your pipeline. (When your run your pipeline, it pick up a agent defined in pool to run your pipeline tasks)
The mapping to the folders in the agent machine is showing as below screenshot. Check the predefined variables for more information.
$(Agent.BuildDirectory) is mapped to c:\agent_work\1
$(Build.ArtifactStagingDirectory) is mapped to c:\agent_work\1\a
$(Build.BinariesDirectory) is mapped to c:\agent_work\1\b
$(Build.SourcesDirectory) is mapped to c:\agent_work\1\s
So back to the question how to deploying a NestJS application to Azure?
First you need to create a service connection in Azure devops to connect to your azure subscription. Check here for detailed steps.
Then add Azure App Service Deploy task/Azure Web App task to the end of your pipeline. See below example:
- task: AzureRmWebAppDeployment#4
inputs:
ConnectionType: 'AzureRM'
azureSubscription: 'SubscriptionServiceConnectionName'
appType: 'webAppLinux'
WebAppName: 'MyWebAppName'
Package: '$(Build.ArtifactStagingDirectory)/dist/'
StartupCommand: 'npm run start:prod'
You can check here for more information.
I'm trying to run an npm install and test on Visual Studio Team Services Build (configuring the build using YAML). I have the following definition.
** updated **
queue:
name: Hosted VS2017
demands: npm
steps:
- task: NodeTool#0
inputs:
versionSpec: "8.x"
task: Npm#1
inputs:
command: "custom"
verbose: "false"
customCommand: "install #angular/cli -g"
task: Npm#1
inputs:
verbose: "false"
task: CmdLine#1
inputs:
filename: "ng"
arguments: "test --watch=false --single-run=true --reporters=junit,progress"
task: PublishTestResults#2
inputs:
testResultsFiles: "**\test.xml"
testRunTitle: "Jasmine Tests"
The install runs fine, but I get an error on the test step:
85% chunk id optimization 86% hashing 87% module assets processing 88% chunk assets processing 89% additional chunk assets processing 90% recording 91% additional asset processing 92% chunk asset optimization 94% asset optimization 95% emitting
2017-12-06T06:21:34.7643927Z ##[error]Process completed with exit code 1.
2017-12-06T06:21:34.7682485Z ##[section]Finishing: Run Tests
I'm using puppeteer to workaround lack of chrome to run the tests.
Using this code instead:
queue: Hosted VS2017
steps:
- script: echo installing packages
- task: Npm#1
displayName: npm install
inputs:
command: install
- task: Npm#1
displayName: npm test
inputs:
command: custom
customCommand: run test
BTW, you need add #angular/cli dependency in package.json to install angular cli during running npm install command.
Finally got it working, but not 100% satisfied with the solutiuon, posting here the progress and open points plus detailed info to reproduce it, hope it can help other and that we can refine it.
Scenario: I'm in the need of configuring CI on an Angular 4 project and running it under Visual Studio Team Service CI hosted environment, and I want to use the yaml based config.
Issues that I have found:
Hosted enviroment come with old node version (1).
Chrome is not installed by default on the hosted environment, phantom browser is not anymore a solution since it's an abandoned project.
You need to install angular-cli globally.
The current working solution I got, steps:
On your project:
Open your command prompt, install puppeteer, karma-junit-reporter
npm install puppeteer karma-junit-reporter --save-dev
Configure your karma.conf.js
At the top of your file add the following line of code
process.env.CHROME_BIN = require('puppeteer').executablePath();
Then on the pluging sections (add karma-junit-reporter)
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-junit-reporter'), // add karma-unit reporter
require('karma-coverage-istanbul-reporter'),
require('#angular/cli/plugins/karma')
],
On the reporters section set junit reporter as a valid one,and configure it:
reporters: config.angularCli && config.angularCli.codeCoverage
? ['progress', 'coverage-istanbul', 'junit']
: ['progress', 'kjhtml', 'junit'],
junitReporter: {
outputDir: '',
outputFile: 'test.xml',
},
Now it's time to add on the root of your project a file named .vsts-ci.yml (just pasted the raw content in this link: https://pastebin.com/0XpmpPrp)
queue:
name: Hosted VS2017
demands: npm
steps:
- task: NodeTool#0
displayName: "Updating node to version 8.x"
inputs:
versionSpec: "8.x"
task: Npm#1
displayName: "installing angular-cli"
inputs:
command: "custom"
verbose: "false"
customCommand: "install #angular/cli#1.0.2 -g"
task: Npm#1
inputs:
verbose: "false"
task: CmdLine#1
displayName: "run tests: ng test"
inputs:
filename: "ng"
arguments: "test --watch=false --single-run=true --reporters=junit,progress"
task: PublishTestResults#2
displayName: "Publish Test Results (test.xml)"
inputs:
testResultsFiles: "**\test.xml"
testRunTitle: "Jasmine Tests"
What it does:
Update node version.
Globally install angular-cli (I stick to the version that is being used in the package).
Execute a noop command (I don't know why it's needed, but if I don't add this it breaks).
Execute ng test (single run and using junit as reporter).
Publish test results.
Tips and interesting posts I have found:
Use the UI build tool to create the build, then there is an option to convert it to yaml.
Node tool updated task: https://learn.microsoft.com/en-us/vsts/build-release/tasks/tool/node-js
Puppeteer and VSTS: http://benjaminspencer.me/post/14/headless-chrome-vsts
Angular 4 and VSTS (I): https://csharperimage.jeremylikness.com/2016/12/integrating-angular-2-unit-tests-with.html
Angular 4 and VSTS (II): https://blogs.msdn.microsoft.com/premier_developer/2017/05/17/integrating-angular-4-unit-tests-with-visual-studio-team-services-vsts/
Room for improvement:
Avoid having to install angular-cli globally, tried to add a custom script to my package-json, but when I call something like "npm run test:ci" it's not recognized by the visual studio build runner.
I would like to get rid of puppeteer, is karma-jsdom-launcher an option?