โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ
โ โโโโโโโโโโโโโโโ โโโโโโ โโโโ โโโโโโโโโโโโโโโ โโโ โโโโโโโ โโโโโโโ โโโ โโโ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโ โโโโ
โ โโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโ โโ โโโโโโ โโโโโโโโโโโโโโโโโโ
โ โโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโ
โ โโโ โโโ โโโโโโ โโโโโโ โโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโ โโโ
โ โโโ โโโ โโโโโโ โโโโโโ โโโโโโโโโโโ โโโโโโโโ โโโโโโโ โโโ โโโโโโ โโโ
โ โ
โ โโโโโโโโโโโ โโโ โโโโโโโ โโโ โโโ โโโโโโโโโโโโโโโ โโโโโโโ โโโโ โโโ
โ โโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโ
โ โโโโโโ โโโ โโโโโโ โโโโโโ โโโ โโโ โโโ โโโโโโ โโโโโโโโโ โโโ
โ โโโโโโ โโโโ โโโโโโโ โโโโโโ โโโ โโโ โโโ โโโโโโ โโโโโโโโโโโโโ
โ โโโโโโโโ โโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโ โโโ โโโโโโโโโโโโโโโ โโโโโโ
โ โโโโโโโโ โโโโโ โโโโโโโ โโโโโโโโ โโโโโโโ โโโ โโโ โโโโโโโ โโโ โโโโโ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๐น๏ธ THE ULTIMATE FRAMEWORK TIME TRAVEL EXPERIENCE ๐น๏ธ
From 2010 Legacy โ 2024 Modern Architecture
Welcome to the Framework Evolution Lab ๐งฌ
Step into the neon-lit corridors of frontend history! This lab takes you on an epic journey through time โ from the golden age of AngularJS 1.6 (circa 2010) to the cutting-edge frontier of React 18 or Angular 17 with TypeScript.
Your Mission: Modernize GlobalTravel Corp's legacy travel booking portal โ a full-featured AngularJS application complete with Bower packages, Grunt builds, jQuery plugins, and all the nostalgic anti-patterns of yesteryear. Transform it into a blazing-fast, type-safe, modern single-page application! ๐
FRAMEWORK EVOLVED ๐งฌ
- Assess migration complexity and scope for AngularJS applications
- Map AngularJS controllers + templates โ React functional components OR Angular standalone components
- Migrate
$scopeand$rootScopeโ React hooks/Zustand OR Angular signals/NgRx - Convert UI-Router states โ TanStack Router OR Angular Router
BOWER โ NPM UPGRADE โฌ๏ธ
- Replace deprecated Bower with modern npm/pnpm
- Eliminate jQuery dependencies (write native components instead!)
- Swap Moment.js โ date-fns (reduce bundle size by 80%!)
- Remove unnecessary Lodash usage (modern ES6+ has you covered!)
GRUNT โ VITE SPEEDRUN ๐๏ธ
- Rip out the Grunt pipeline (goodbye, complex config!)
- Install Vite (React) or Angular CLI (Angular) โ lightning-fast builds โก
- Hot Module Replacement (HMR) that actually works
- Build times: from minutes โ seconds
TYPESCRIPT UNLOCKED ๐
- Convert loosely-typed JavaScript โ strict TypeScript
- Catch runtime errors at compile time
- IntelliSense superpowers in your IDE
- Refactor with confidence using type safety
DEPLOYMENT MASTERY ๐
- Build production-optimized bundles
- Deploy to Azure Static Web Apps
- Set up CI/CD with GitHub Actions
This lab offers TWO PARALLEL UNIVERSES for your migration destination:
React 18 + TypeScript
โโโ โก Vite (build tool)
โโโ ๐งญ TanStack Router (routing)
โโโ ๐ TanStack Query (API state)
โโโ ๐ป Zustand (global state)
โโโ ๐งช Vitest + Testing Library (tests)
โโโ ๐จ Modern CSS Modules
Choose React if:
- โ You want maximum flexibility and ecosystem richness
- โ Your team prefers functional programming patterns
- โ You need a lightweight, composable architecture
- โ You're building component libraries or design systems
Angular 17 + TypeScript
โโโ ๐ ๏ธ Angular CLI (build tool)
โโโ ๐งญ Angular Router (routing)
โโโ ๐ HttpClient + Interceptors (API)
โโโ ๐ช NgRx (global state)
โโโ ๐งช Jasmine + TestBed (tests)
โโโ ๐จ Angular Material (UI components)
Choose Angular if:
- โ Your team already knows AngularJS and wants a familiar migration
- โ You need a batteries-included framework with opinionated structure
- โ Enterprise-grade type safety and dependency injection are priorities
- โ You prefer a full-featured framework over composing libraries
๐ก Pro Tip: Both paths achieve the same outcome! The lab includes complete implementations for both React and Angular. You can even migrate to both and compare! ๐
Before you jack into the mainframe, make sure you have:
-
๐ง Knowledge:
- JavaScript fundamentals
- AngularJS 1.x familiarity (controllers, directives, services)
- TypeScript basics (or willingness to learn!)
- Understanding of REST APIs
-
๐ป System Requirements:
- Node.js 20+ installed (Download)
- npm (comes with Node) or pnpm
- Git (for version control)
- Your favorite code editor (VS Code recommended)
-
โ๏ธ Azure (Optional for deployment):
- Azure subscription (Free tier available)
- Azure CLI installed
-
๐ฆ Legacy Tools (for running the AngularJS app):
- Bower:
npm install -g bower - Grunt CLI:
npm install -g grunt-cli
- Bower:
# Clone the repository
git clone https://github.com/EmeaAppGbb/appmodlab-angularjs-to-react-angular-modern.git
cd appmodlab-angularjs-to-react-angular-modern
# Check out the legacy branch
git checkout legacy
# Install legacy dependencies (Bower + npm)
bower install
npm install
# Start the mock API server
node api-mock/server.js &
# Build the AngularJS app with Grunt
grunt build
# Serve the legacy app
grunt serve๐ Open http://localhost:8080 and witness the glory of 2010's finest frontend tech!
For React:
git checkout solution
npm install
npm run devFor Angular:
git checkout solution-angular
npm install
npm startEach migration step has its own branch:
git checkout step-1-project-setup # Vite/Angular CLI scaffold
git checkout step-2-component-migration # Controllers โ Components
git checkout step-3-state-management # $scope โ hooks/signals
git checkout step-4-routing-and-api # UI-Router โ modern router
git checkout step-5-testing-and-deploy # Tests + Azure deploymentglobaltravel-portal/
โโโ ๐ฆ bower.json # Bower dependencies (deprecated)
โโโ โ๏ธ Gruntfile.js # Grunt build config (complex!)
โโโ ๐จ app/
โ โโโ app.js # AngularJS module definition
โ โโโ app.routes.js # UI-Router state configs
โ โโโ components/
โ โ โโโ ๐ซ flight-search/ # Flight search feature
โ โ โโโ ๐จ hotel-booking/ # Hotel reservation
โ โ โโโ ๐ itinerary/ # Trip itinerary manager
โ โ โโโ ๐ travel-request/ # Approval workflow
โ โ โโโ ๐ฐ expense-reconciliation/ # Expense reports
โ โโโ directives/ # Custom AngularJS directives
โ โ โโโ date-picker.directive.js # jQuery datepicker wrapper
โ โ โโโ currency-input.directive.js
โ โ โโโ approval-status.directive.js
โ โโโ filters/ # AngularJS filters
โ โ โโโ currency.filter.js
โ โ โโโ date-format.filter.js
โ โโโ services/ # AngularJS services
โ โ โโโ auth.service.js # Authentication with $http
โ โ โโโ api.service.js # Restangular config
โ โ โโโ user.service.js # User profile
โ โโโ assets/
โ โโโ css/ # Bootstrap 3 + custom styles
โ โโโ images/
โโโ ๐งช test/spec/ # Karma + Jasmine tests
โโโ ๐ api-mock/
โโโ server.js # Express mock API server
globaltravel-portal-react/
โโโ ๐ฆ package.json # npm dependencies
โโโ โก vite.config.ts # Vite build config (simple!)
โโโ ๐จ src/
โ โโโ main.tsx # App entry point
โ โโโ App.tsx # Root component
โ โโโ router.tsx # TanStack Router config
โ โโโ components/
โ โ โโโ ๐ซ FlightSearch/ # React functional component
โ โ โโโ ๐จ HotelBooking/
โ โ โโโ ๐ Itinerary/
โ โ โโโ ๐ TravelRequest/
โ โ โโโ ๐ฐ ExpenseReconciliation/
โ โโโ hooks/ # Custom React hooks
โ โ โโโ useAuth.ts
โ โ โโโ useFlights.ts
โ โ โโโ useHotels.ts
โ โโโ store/ # Zustand stores
โ โ โโโ authStore.ts
โ โ โโโ userStore.ts
โ โโโ api/ # TanStack Query + Axios
โ โ โโโ client.ts
โ โโโ utils/ # Utility functions
โ โโโ dateHelpers.ts # date-fns wrappers
โโโ ๐งช tests/ # Vitest + Testing Library
globaltravel-portal-angular/
โโโ ๐ฆ package.json # npm dependencies
โโโ ๐ ๏ธ angular.json # Angular CLI config
โโโ ๐จ src/
โ โโโ main.ts # App bootstrap
โ โโโ app/
โ โ โโโ app.config.ts # App configuration
โ โ โโโ app.routes.ts # Angular Router config
โ โ โโโ components/
โ โ โ โโโ ๐ซ flight-search/ # Standalone component
โ โ โ โโโ ๐จ hotel-booking/
โ โ โ โโโ ๐ itinerary/
โ โ โ โโโ ๐ travel-request/
โ โ โ โโโ ๐ฐ expense-reconciliation/
โ โ โโโ services/ # Angular services
โ โ โ โโโ auth.service.ts
โ โ โ โโโ flight.service.ts
โ โ โ โโโ hotel.service.ts
โ โ โโโ store/ # NgRx store
โ โ โ โโโ actions/
โ โ โ โโโ reducers/
โ โ โ โโโ selectors/
โ โ โโโ interceptors/ # HTTP interceptors
โ โ โโโ auth.interceptor.ts
โโโ ๐งช tests/ # Jasmine + TestBed
| Technology | Version | Status | Reason for Replacement |
|---|---|---|---|
| 1.6.x | โ EOL (2022) | No security patches, poor performance, no TypeScript | |
| ๐ฆ Bower | 1.8.x | โ Deprecated | Unmaintained since 2017, replaced by npm |
| โ๏ธ Grunt | 1.x | Slow builds, complex config, replaced by Vite/CLI | |
| ๐ฒ jQuery | 2.x | DOM manipulation done by React/Angular | |
| ๐ง Restangular | 1.6.x | Extra abstraction layer over $http | |
| ๐ Moment.js | 2.x | Huge bundle size (67KB), use date-fns (12KB) | |
| ๐จ Lodash | 4.x | Many functions available in modern ES6+ | |
| โ Karma + Jasmine | - | Replaced by Vitest (React) or modern Jasmine (Angular) |
- โ
$scope-based data binding (notcontrollerAssyntax) - โ
$rootScopeevents for cross-component communication ($broadcast/$on) - โ jQuery plugins wrapped in AngularJS directives (DOM manipulation conflicts)
- โ
$watchand$watchCollectionfor manual change detection - โ Two-way data binding causing performance issues on large lists
- โ No TypeScript โ dynamic typing leading to runtime errors
- โ Mixed jQuery and AngularJS DOM manipulation
- โ Global namespace pollution
React Path:
| Technology | Version | Why It's Better |
|---|---|---|
| โ๏ธ React | 18.x | Virtual DOM, hooks, huge ecosystem, 200K+ weekly downloads |
| ๐ TypeScript | 5.x | Type safety, IntelliSense, refactoring confidence |
| โก Vite | 5.x | Lightning-fast builds (10x faster than Webpack), HMR in <50ms |
| ๐งญ TanStack Router | 1.x | Type-safe routing, nested routes, data loading |
| ๐ TanStack Query | 5.x | Server state management, caching, background refetch |
| ๐ป Zustand | 4.x | Lightweight global state (1KB), no boilerplate |
| ๐ date-fns | 3.x | Modular, tree-shakeable, 80% smaller than Moment.js |
| ๐งช Vitest | 1.x | Fast tests with Vite, Jest-compatible API |
Angular Path:
| Technology | Version | Why It's Better |
|---|---|---|
| 17.x | Signals, standalone components, improved DX, enterprise-grade | |
| ๐ TypeScript | 5.x | First-class citizen in Angular, full type safety |
| ๐ ๏ธ Angular CLI | 17.x | Optimized builds, built-in best practices |
| ๐งญ Angular Router | 17.x | Feature-rich routing, guards, lazy loading |
| ๐ HttpClient | 17.x | RxJS-powered, interceptors, automatic JSON parsing |
| ๐ช NgRx | 17.x | Redux pattern, DevTools, time-travel debugging |
| ๐จ Angular Material | 17.x | Production-ready components, accessibility built-in |
| ๐งช Jasmine + TestBed | - | Powerful testing utilities, dependency injection |
BEFORE (AngularJS): AFTER (React/Angular):
โโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Controller + $scope โ โโโโโโโโโโโโโบ โ Functional Component โ
โ (Two-way binding) โ โ (React Hooks/Signals) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ $rootScope Events โ โโโโโโโโโโโโโบ โ Zustand/NgRx Store โ
โ ($broadcast/$on) โ โ (Immutable state) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ UI-Router States โ โโโโโโโโโโโโโบ โ TanStack/Angular Routerโ
โ (config-based) โ โ (Type-safe routes) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ jQuery Directives โ โโโโโโโโโโโโโบ โ Native Components โ
โ (DOM manipulation) โ โ (Virtual DOM/Signals) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Restangular + $http โ โโโโโโโโโโโโโบ โ TanStack Query/HttpClt โ
โ (Promise-based) โ โ (Observable/async) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Bower + Grunt โ โโโโโโโโโโโโโบ โ npm + Vite/CLI โ
โ (Slow builds) โ โ (HMR in milliseconds) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโ
This lab is designed to be completed with GitHub Copilot CLI as your co-pilot! The CLI can help you:
- ๐ Analyze legacy code patterns
- ๐ Generate migration code snippets
- ๐งช Write unit tests automatically
- ๐ Document your changes
- ๐ Debug build errors
Quick Copilot CLI Tips:
# Ask Copilot to explain legacy code
@workspace /explain How does the AngularJS flight-search controller work?
# Generate migration code
@workspace /new Create a React functional component equivalent to this AngularJS controller
# Fix build errors
@terminal Why is Vite failing to build?
# Generate tests
@workspace /new Write Vitest tests for the FlightSearch componentObjective: Get the AngularJS app running and understand its features.
- Check out the
legacybranch - Install Bower dependencies:
bower install - Install npm dependencies:
npm install - Start the mock API:
node api-mock/server.js - Build with Grunt:
grunt build - Run the app:
grunt serve - Explore all features:
- ๐ซ Search for flights (JFK โ LAX)
- ๐จ Book a hotel
- ๐ View your itinerary
- ๐ Submit a travel request for approval
- ๐ฐ Reconcile expenses
๐ก Copilot Tip: Use @workspace /explain to understand how each AngularJS controller, service, and directive works.
Objective: Inventory all AngularJS components and plan the migration.
What to Analyze:
- Controllers: How many? Which ones are most complex?
- Directives: Which are reusable? Which wrap jQuery plugins?
- Services: Which make API calls? Which manage state?
- Filters: Which are used frequently?
- Routes: How many UI-Router states?
- Dependencies: Bower packages to replace with npm equivalents
๐ก Copilot Tip: Ask Copilot to create a migration checklist for you:
@workspace Create a checklist of all AngularJS controllers and their React/Angular equivalentsReact Path:
# Create Vite + React + TypeScript project
npm create vite@latest globaltravel-portal-react -- --template react-ts
cd globaltravel-portal-react
# Install dependencies
npm install
npm install @tanstack/router @tanstack/react-query zustand axios date-fns
# Install dev dependencies
npm install -D vitest @testing-library/react @testing-library/jest-domAngular Path:
# Create Angular 17 project
npx @angular/cli@17 new globaltravel-portal-angular --standalone --routing --style=scss
cd globaltravel-portal-angular
# Install dependencies
npm install @ngrx/store @ngrx/effects @angular/material date-fns
# Install dev dependencies
npm install -D @ngrx/store-devtools๐ก Copilot Tip: Ask Copilot to generate the project structure:
@workspace /new Create a folder structure for the React/Angular migrationObjective: Convert AngularJS controllers + templates to React/Angular components.
Migration Pattern (React):
Before (AngularJS Controller):
// flight-search.controller.js
angular.module('app').controller('FlightSearchController',
function($scope, FlightService) {
$scope.searchParams = { origin: '', destination: '' };
$scope.flights = [];
$scope.searchFlights = function() {
FlightService.search($scope.searchParams).then(function(data) {
$scope.flights = data;
});
};
}
);After (React Component):
// FlightSearch.tsx
import { useState } from 'react';
import { useQuery } from '@tanstack/react-query';
import { searchFlights } from '@/api/flightService';
export const FlightSearch = () => {
const [searchParams, setSearchParams] = useState({ origin: '', destination: '' });
const { data: flights, refetch } = useQuery({
queryKey: ['flights', searchParams],
queryFn: () => searchFlights(searchParams),
enabled: false,
});
return (
<div>
{/* Component JSX */}
</div>
);
};Migration Pattern (Angular):
After (Angular Standalone Component):
// flight-search.component.ts
import { Component, signal } from '@angular/core';
import { FlightService } from '@/services/flight.service';
@Component({
selector: 'app-flight-search',
standalone: true,
templateUrl: './flight-search.component.html',
})
export class FlightSearchComponent {
searchParams = signal({ origin: '', destination: '' });
flights = signal([]);
constructor(private flightService: FlightService) {}
searchFlights() {
this.flightService.search(this.searchParams()).subscribe(
data => this.flights.set(data)
);
}
}๐ก Copilot Tip:
@workspace Convert this AngularJS controller to a React functional component with hooksRepeat for each component:
- โ FlightSearch
- โ HotelBooking
- โ Itinerary
- โ TravelRequest
- โ ExpenseReconciliation
Objective: Replace $scope and $rootScope with modern state management.
Before (AngularJS):
// Using $rootScope for global auth state
$rootScope.$on('user:loggedIn', function(event, user) {
$scope.currentUser = user;
});
$rootScope.$broadcast('user:loggedIn', userData);After (React + Zustand):
// store/authStore.ts
import { create } from 'zustand';
export const useAuthStore = create((set) => ({
currentUser: null,
login: (user) => set({ currentUser: user }),
logout: () => set({ currentUser: null }),
}));
// Use in components
const { currentUser, login } = useAuthStore();After (Angular + NgRx):
// store/actions/auth.actions.ts
import { createAction, props } from '@ngrx/store';
export const loginSuccess = createAction(
'[Auth] Login Success',
props<{ user: User }>()
);
// Use in components
this.store.dispatch(loginSuccess({ user }));
this.currentUser$ = this.store.select(selectCurrentUser);Before (UI-Router):
// app.routes.js
$stateProvider
.state('flights', {
url: '/flights',
templateUrl: 'components/flight-search/flight-search.template.html',
controller: 'FlightSearchController'
});After (TanStack Router - React):
// router.tsx
import { createRoute } from '@tanstack/router';
import { FlightSearch } from '@/components/FlightSearch';
const flightsRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/flights',
component: FlightSearch,
});After (Angular Router):
// app.routes.ts
import { Routes } from '@angular/router';
import { FlightSearchComponent } from './components/flight-search';
export const routes: Routes = [
{ path: 'flights', component: FlightSearchComponent },
];Objective: Remove legacy libraries and use modern alternatives.
Replacements:
- โ jQuery โ โ Native React/Angular (no DOM manipulation needed!)
- โ Moment.js โ โ date-fns
- โ Lodash โ โ Native ES6+ (map, filter, reduce, etc.)
- โ Restangular โ โ TanStack Query + Axios (React) or HttpClient (Angular)
Example (date-fns):
// Before (Moment.js) - 67KB bundle
import moment from 'moment';
const formattedDate = moment(date).format('YYYY-MM-DD');
// After (date-fns) - 12KB bundle
import { format } from 'date-fns';
const formattedDate = format(date, 'yyyy-MM-dd');React (Vitest + Testing Library):
// FlightSearch.test.tsx
import { render, screen, fireEvent } from '@testing-library/react';
import { FlightSearch } from './FlightSearch';
test('searches for flights when form is submitted', async () => {
render(<FlightSearch />);
fireEvent.change(screen.getByLabelText('Origin'), { target: { value: 'JFK' } });
fireEvent.change(screen.getByLabelText('Destination'), { target: { value: 'LAX' } });
fireEvent.click(screen.getByText('Search'));
expect(await screen.findByText('Flight Results')).toBeInTheDocument();
});Angular (Jasmine + TestBed):
// flight-search.component.spec.ts
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { FlightSearchComponent } from './flight-search.component';
describe('FlightSearchComponent', () => {
let component: FlightSearchComponent;
let fixture: ComponentFixture<FlightSearchComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [FlightSearchComponent]
}).compileComponents();
fixture = TestBed.createComponent(FlightSearchComponent);
component = fixture.componentInstance;
});
it('should search for flights', () => {
component.searchParams.set({ origin: 'JFK', destination: 'LAX' });
component.searchFlights();
expect(component.flights().length).toBeGreaterThan(0);
});
});Azure Static Web Apps Deployment:
# Install Azure CLI
az login
# Create resource group
az group create --name rg-globaltravel --location eastus
# Create Static Web App
az staticwebapp create \
--name globaltravel-portal \
--resource-group rg-globaltravel \
--source https://github.com/YOUR_USERNAME/globaltravel-portal-react \
--location eastus \
--branch main \
--app-location "/" \
--output-location "dist"
# GitHub Actions workflow is auto-generated!๐ก Copilot Tip:
@workspace Create a GitHub Actions workflow for building and deploying to Azure Static Web Apps| Stage | Time | Difficulty |
|---|---|---|
| 1๏ธโฃ Run Legacy App | 30 min | โญ Easy |
| 2๏ธโฃ Analyze Scope | 45 min | โญโญ Medium |
| 3๏ธโฃ Scaffold Project | 30 min | โญ Easy |
| 4๏ธโฃ Migrate Components | 2-3 hours | โญโญโญ Hard |
| 5๏ธโฃ State Management | 1-2 hours | โญโญโญ Hard |
| 6๏ธโฃ Routing | 1 hour | โญโญ Medium |
| 7๏ธโฃ Replace Dependencies | 1 hour | โญโญ Medium |
| 8๏ธโฃ Testing | 1-2 hours | โญโญโญ Hard |
| 9๏ธโฃ Deploy to Azure | 30 min | โญโญ Medium |
| TOTAL | 5-7 hours | โญโญโญ Advanced |
๐ก Pro Tip: You can complete this lab over multiple sessions. Use the step branches to save your progress!
React:
Angular:
Migration Guides:
- You Might Not Need Lodash
- You Might Not Need Moment.js
- React Hooks Best Practices
- Angular Signals Guide
Legacy App:
- AngularJS app runs successfully with Bower + Grunt
- All 5 features work (flights, hotels, itinerary, travel requests, expenses)
- Mock API serves data correctly
Modern App (React OR Angular):
- TypeScript compiles with zero errors
- All components migrated from AngularJS
- State management implemented (Zustand/NgRx)
- Routing works for all pages
- No jQuery, Moment.js, Bower, or Grunt in dependencies
- Build completes in <10 seconds (Vite/CLI)
- All tests pass
- App deploys to Azure Static Web Apps
- Lighthouse score >90 for Performance
Code Quality:
- TypeScript strict mode enabled
- ESLint passes with zero warnings
- No console.log statements in production
- Proper error handling for API calls
- Accessible (WCAG AA compliant)
Problem: Bower install fails
# Solution: Use legacy peer deps
npm install -g bower --legacy-peer-depsProblem: Grunt build is slow
# Solution: This is normal for Grunt! That's why we're migrating. โฐ
# Consider using --force flag if needed
grunt build --forceProblem: React app won't compile
# Solution: Clear cache and reinstall
rm -rf node_modules package-lock.json
npm install
npm run devProblem: Angular CLI version mismatch
# Solution: Install Angular 17 globally
npm install -g @angular/cli@17
ng versionProblem: Azure deployment fails
# Solution: Check GitHub Actions logs
# Ensure output-location matches your build folder (dist/build)Upon completing this lab, you will have earned:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ
โ ๐ FRAMEWORK EVOLUTION MASTER ๐ โ
โ โ
โ โจ You successfully time-traveled from 2010 to 2024! โ
โ โ
โ Skills Acquired: โ
โ ๐งฌ AngularJS โ React/Angular Migration โ
โ โฌ๏ธ Bower โ npm Modernization โ
โ ๐๏ธ Grunt โ Vite/CLI Speedrun โ
โ ๐ JavaScript โ TypeScript Mastery โ
โ ๐ Azure Static Web Apps Deployment โ
โ โ
โ Badge: LEGACY DESTROYER ๐ฅ โ
โ Level: SENIOR MIGRATION ENGINEER ๐๏ธ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Need Help?
- ๐ฌ Join the discussion: GitHub Discussions
- ๐ Report issues: GitHub Issues
- ๐ง Contact the team: appmodlabs@microsoft.com
Share Your Success!
- Tweet your completion with #AppModLabs #AngularJSMigration
- Star the repo โญ if you found it helpful
- Contribute improvements via Pull Requests
MIT License - See LICENSE file for details.
_____ _______ _____ _______ __ ______ _ _ _____ __ __ _____ _____ _____ _____ _______ _____ ____ _ _
/ ____|__ __|/\ | __ \__ __| | \/ / \ | | | | __ \ | \/ |_ _/ ____| __ \_ _|__ __|_ _/ __ \| \ | |
| (___ | | / \ | |__) | | | | \ / | \| | | | |__) | | \ / | | || | __| |__) || | | | | || | | | \| |
\___ \ | | / /\ \ | _ / | | | |\/| | . ` | | | _ / | |\/| | | || | |_ | _ / | | | | | || | | | . ` |
____) | | |/ ____ \| | \ \ | | | | | | |\ | | | | \ \ | | | |_| || |__| | | \ \_| |_ | | _| || |__| | |\ |
|_____/ |_/_/ \_\_| \_\ |_| |_| |_|_| \_| |_|_| \_\ |_| |_|_____\_____|_| \_\_____| |_| |_____\____/|_| \_|
๐ฎ INSERT COIN TO CONTINUE ๐ฎ
โฌ๏ธ CLONE THE REPO โข ๐ READ THE FULL LAB โข ๐ START MIGRATING
Powered by โ๏ธ Azure โข Assisted by ๐ค GitHub Copilot