19. Migrating Legacy Projects
Migrating Legacy SAPUI5 Projects to Modern Tooling
Why migrate?
- Legacy projects often use outdated UI5 versions, lack support for modern tools (TypeScript, UI5 Tooling, Fiori Tools), have poor test coverage, and are hard to maintain.
- Migration simplifies maintenance, speeds up development, improves code quality, and enables CI/CD integration.
1. Audit the current state
Example:
Before:
- All code in one
/webappfolder, all controllers in one directory, no module separation. - Uses outdated
Component-preload.js, noui5.yaml.
After:
- Clear separation:
/srcfor new code,/webappfor legacy,ui5.yamlpresent, controllers organized in folders.
2. Switch to UI5 Tooling
Example ui5.yaml:
specVersion: '3.0'
metadata:
name: my.legacy.app
type: application
resources:
configuration:
paths:
webapp: webapp
Command:
npm install --save-dev @ui5/cli
ui5 build
3. Introduce TypeScript
Before:
LegacyController.controller.js
sap.ui.define([
"sap/ui/core/mvc/Controller"
], function(Controller) {
return Controller.extend("my.legacy.app.controller.LegacyController", {
onInit: function() {
// ...
}
});
});
After:
NewFancyController.ts
import Controller from "sap/ui/core/mvc/Controller";
export default class NewFancyController extends Controller {
onInit(): void {
// ...
}
}
tsconfig.json — see 14. TypeScript
4. Refactor architecture
Before:
Each controller has its own utilities, code duplication.
After:
BaseController.ts
import Controller from "sap/ui/core/mvc/Controller";
export default class BaseController extends Controller {
showError(message: string) {
sap.m.MessageBox.error(message);
}
}
MyPage.controller.ts
import BaseController from "./BaseController";
export default class MyPage extends BaseController {
onError() {
this.showError("Something went wrong");
}
}
5. UI migration
Before:
Custom table in XML:
<Table>
<columns>
<Column><Text text="ID"/></Column>
<Column><Text text="Name"/></Column>
</columns>
<items>
<ColumnListItem>
<cells>
<Text text="{id}"/>
<Text text="{name}"/>
</cells>
</ColumnListItem>
</items>
</Table>
After:
Using SmartTable (Fiori Elements):
<smartTable:SmartTable
entitySet="Products"
tableType="Table"
useExportToExcel="true"
useVariantManagement="true"
useTablePersonalisation="true"
header="Products"
showRowCount="true"/>
6. Introduce testing
Before:
No tests.
After:
/webapp/test/unit/model/formatter.js
QUnit.module("formatter", function () {
QUnit.test("should return upper case", function (assert) {
var sText = formatter.upperCase("test");
assert.strictEqual(sText, "TEST");
});
});
E2E:
/e2e/test.spec.js (wdi5)
describe("App", () => {
it("should open the main page", async () => {
await browser.url("/");
const title = await browser.$("id=mainTitle");
expect(await title.getText()).toBe("Main");
});
});
7. Automation and CI/CD
Example GitHub Actions workflow:
name: UI5 CI
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install dependencies
run: npm install
- name: Build UI5 app
run: ui5 build
- name: Run unit tests
run: npm test
Best practices
- Migrate step by step: don’t try to rewrite everything at once. Start with infrastructure, then migrate individual modules.
- Cover changes with tests: this reduces regression risks.
- Use generators: for new modules and apps, use yo @sap/fiori.
- Document architectural decisions: helps with onboarding new developers.
- Remove legacy code: don’t be afraid to get rid of outdated utilities and patterns.
Pitfalls
Before:
Custom component that doesn’t work after UI5 update.
Solution:
- Check the UI5 changelog.
- Rewrite the component using standard APIs.
- Add tests for critical functions.
Useful links
Migration is not just about new tools, but about development culture:
- Write tests for every new module.
- Use linters and autotests.
- Document architectural decisions.
Migration is not a one-time task, but a process. The sooner you start, the easier it will be to maintain the project in the future.