Skip to content

Commit dcc8080

Browse files
committed
[RFC] 0004 Simple Build Extensibility
1 parent 823ad30 commit dcc8080

File tree

1 file changed

+158
-0
lines changed

1 file changed

+158
-0
lines changed
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
- Start Date: 2018-08-28
2+
- RFC PR: [#](https://github.com/SAP/ui5-tooling/pull/)
3+
- Issue: -
4+
- Affected components
5+
+ [x] [ui5-builder](https://github.com/SAP/ui5-builder)
6+
+ [ ] [ui5-server](https://github.com/SAP/ui5-server)
7+
+ [ ] [ui5-cli](https://github.com/SAP/ui5-cli)
8+
+ [ ] [ui5-fs](https://github.com/SAP/ui5-fs)
9+
+ [x] [ui5-project](https://github.com/SAP/ui5-project)
10+
+ [ ] [ui5-logger](https://github.com/SAP/ui5-logger)
11+
12+
# RFC 0004 Simple Build Extensibility
13+
## Summary
14+
Add a feature for basic customization of how a single UI5 project is being built.
15+
16+
## Motivation
17+
Currently the UI5 build is only capable of building UI5 projects of types "application" and "library" with a fixed set of tasks to be executed.
18+
19+
A UI5 project (for example a library) may want to add build steps. For this, an extensibility mechanism is needed.
20+
21+
While multiple UI5 projects may require the same kind of "customized" build, easy reuse capabilities are not in focus of this RFC. [RFC 0001](https://github.com/SAP/ui5-tooling/pull/4) focuses more on that.
22+
23+
This shall be a preliminary solution to allow for basic extensibility and to learn about the different needs and use cases in that area before proceeding with [RFC 0001](https://github.com/SAP/ui5-tooling/pull/4) or similar concepts.
24+
25+
## Detailed design
26+
### Configuration
27+
In a projects `ui5.yaml`, a new configuration option should be added to define additional tasks that shall be executed at a specific time during the build process of a project. This configuration shall only affect the project it belongs to. The build process of any of the other projects (e.g. project dependencies) shall be unaffected by this configuration.
28+
29+
A task may require certain tasks to be executed before and after it. This shall be configurable in a simple but less generic way. See [RFC 0001](https://github.com/SAP/ui5-tooling/pull/4) for a concept of a more generic handling.
30+
31+
A project configuration might look like this:
32+
```yaml
33+
specVersion: "0.1"
34+
type: library
35+
metadata:
36+
name: my.library
37+
builder:
38+
customTasks:
39+
- name: babel
40+
beforeTask: generateComponentPreload
41+
- name: generateMarkdownFiles
42+
afterTask: uglify
43+
configuration:
44+
color: blue
45+
```
46+
47+
When building "my.library", this will execute the custom task *babel* before the "standard" task *generateComponentPreload* and *generateMarkdownFiles* after *uglify*. This means that for example *generateComponentPreload* and all following tasks can work with the resources created or modified by the *babel* task.
48+
49+
### Generic handling of extension
50+
**This section is partially equal to what is outlined in [RFC 0001](https://github.com/SAP/ui5-tooling/blob/rfc-type-ext/rfcs/0001-type-extensibility.md#generic-handling-of-extension).**
51+
52+
Custom task implementations have similar characteristics than other possible "extensions" of the UI5 Build and Development Tooling. Examples for other extensions include "Shims" (see RFC 0002), server middlewares and translators.
53+
54+
Therefore a somewhat generic concept for dealing with extensions is needed.
55+
56+
To separate "UI5 Projects" (i.e. things that represent UI5-artifacts for the browser) from tooling specific things like "extensions", an additional attribute "kind" is added to the ui5.yaml.
57+
58+
A custom task (a.k.a. "task extension") will consist of at least a ui5.yaml defining it as an extension and a JavaScript implementation.
59+
60+
#### Example task extension
61+
**`ui5.yaml`**:
62+
```yaml
63+
specVersion: "0.1"
64+
kind: extension
65+
type: task
66+
metadata:
67+
name: generateMarkdownFiles
68+
task:
69+
path: generateMarkdownFiles.js
70+
```
71+
72+
**`generateMarkdownFiles.js`**:
73+
```js
74+
const markdownGenerator = require("./markdownGenerator");
75+
76+
module.exports = function({workspace, options}) {
77+
return workspace.byGlob("**/*.txt")
78+
.then((textResources) => {
79+
return markdownGenerator({
80+
resources: textResources
81+
});
82+
})
83+
.then((markdownResources) => {
84+
return Promise.all(markdownResources.map((resource) => {
85+
return workspace.write(resource);
86+
}));
87+
});
88+
};
89+
```
90+
91+
#### Collecting and applying task extensions
92+
A task extension might be a standalone module or part of a project.
93+
94+
If the extension is part of a project, the single `ui5.yaml` for the above example might look like this:
95+
96+
```yaml
97+
specVersion: "0.1"
98+
kind: project
99+
type: library
100+
metadata:
101+
name: my.library
102+
builder:
103+
customTasks:
104+
- name: generateMarkdownFiles
105+
afterTask: uglify
106+
configuration:
107+
color: blue
108+
----
109+
specVersion: "0.1"
110+
kind: extension
111+
type: task
112+
metadata:
113+
name: generateMarkdownFiles
114+
task:
115+
path: generateMarkdownFiles.js
116+
```
117+
118+
In this case the extension is no dependency of any kind but automatically collected and processed with the processing of the project.
119+
120+
The AbstractBuilder will detect the custom task configuration of the project my.library and inject the tasks into the build execution.
121+
122+
123+
### Task implementation
124+
A custom task implementation needs to return a function with the following signature (written in JSDoc):
125+
126+
```js
127+
/**
128+
* Custom task example
129+
*
130+
* @param {Object} parameters Parameters
131+
* @param {DuplexCollection} parameters.workspace DuplexCollection to read and write files
132+
* @param {AbstractReader} parameters.dependencies Reader or Collection to read dependency files
133+
* @param {Object} parameters.options Options
134+
* @param {string} parameters.options.projectName Project name
135+
* @param {string} [parameters.options.configuration] Task configuration if given in ui5.yaml
136+
* @returns {Promise<undefined>} Promise resolving with undefined once data has been written
137+
*/
138+
module.exports = function({workspace, options}) {
139+
// [...]
140+
};
141+
```
142+
143+
## How we teach this
144+
- Documentation about how to implement custom tasks
145+
- Explanation of the task/processor concept
146+
147+
## Drawbacks
148+
Custom task configurations might break with future changes to the Application- and LibraryBuilder due to renaming or reordering of the standard tasks.
149+
150+
## Alternatives
151+
There are ways to consume (and thereby possibly adapt) the existing tooling through its API via taskrunners such as grunt or gulp, or using a custom node.js script. But this offers only limited possibilities, especially when it comes to building transient dependencies.
152+
153+
[RFC 0001](https://github.com/SAP/ui5-tooling/pull/4) may offer a more generic way to tackle this but requires additional concept and evaluation work. This RFC (0004) should not prevent the implementation of RFC 0001 in the future.
154+
155+
## Unresolved questions
156+
- Detailed task signature
157+
+ Should the whole `project` object be handed over to custom tasks?
158+

0 commit comments

Comments
 (0)