Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Asset Build Tool #17262

Open
wants to merge 107 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
107 commits
Select commit Hold shift + click to select a range
b4d57c8
Asset build tool
Skrypt Apr 4, 2024
0a226e7
Merge branch 'main' into skrypt/asset-build-tool
Skrypt Apr 12, 2024
e0d37a9
wip yarn build
Skrypt Apr 12, 2024
0c7f561
WIP Asset Build Tool
Skrypt Dec 19, 2024
4354f70
wip AdminMenu Assets.json
Skrypt Dec 19, 2024
979fcf1
Merge branch 'main' into skrypt/asset-build-tool
Skrypt Dec 19, 2024
7857435
wip Build Tool
Skrypt Dec 19, 2024
e045ae5
update SRI
Skrypt Dec 19, 2024
f475527
Use yarn for testing build assets
Skrypt Dec 19, 2024
18ba519
add corepack
Skrypt Dec 19, 2024
b424cde
yarn build instead of rebuild
Skrypt Dec 19, 2024
3314011
Rebuild all
Skrypt Dec 20, 2024
e476a06
Fix CI build
Skrypt Dec 20, 2024
c7325f3
CorePack
Skrypt Dec 20, 2024
e57bc54
Remove postinstall
Skrypt Dec 20, 2024
88510d2
build
Skrypt Dec 20, 2024
e5654ea
update yarn.lock
Skrypt Dec 20, 2024
ab69a7b
Adding gulp process as part of concurently
Skrypt Dec 20, 2024
0a3fc8f
remove gulp-rebuild
Skrypt Dec 20, 2024
3f75b7f
yarn build -g
Skrypt Dec 20, 2024
ab67333
Use gulp rebuild
Skrypt Dec 20, 2024
c3e10e3
Add command options
Skrypt Dec 20, 2024
d93a0cb
Update .scripts/assets-build-tool/Readme.md
Skrypt Dec 21, 2024
ed0c52a
Revert changes in OC.AdminMenu
Skrypt Dec 21, 2024
f854e18
Merge branch 'skrypt/asset-build-tool' of https://github.com/OrchardC…
Skrypt Dec 21, 2024
6bec184
Fix build under linux
Skrypt Jan 6, 2025
9e409c9
use old gulp rebuild
Skrypt Jan 6, 2025
5d63fbc
revert last commit
Skrypt Jan 6, 2025
1f5e8fa
revert
Skrypt Jan 6, 2025
7b97f88
keep npm install for gulp
Skrypt Jan 6, 2025
d5bc9f9
revert assets.json
Skrypt Jan 6, 2025
b225478
update pl
Skrypt Jan 6, 2025
5d6e58a
fix build
Skrypt Jan 6, 2025
96225f6
update yarn.lock
Skrypt Jan 6, 2025
e2ea2af
up pack.jso
Skrypt Jan 6, 2025
28a0c61
yarn cache clean
Skrypt Jan 6, 2025
e74955a
fix assets.json paths
Skrypt Jan 6, 2025
cb54b23
update assets paths
Skrypt Jan 6, 2025
99823ee
fix gulp rebuild
Skrypt Jan 6, 2025
a0dc560
use yarn build -gr
Skrypt Jan 6, 2025
c77e701
Merge branch 'main' into skrypt/asset-build-tool
Skrypt Jan 6, 2025
8d5517b
Use GulpAssets.json and Assets.json
Skrypt Jan 8, 2025
119913b
Add missing dependencies in package.json files
Skrypt Jan 8, 2025
4f71a9b
Add null check on Parcel Bundles
Skrypt Jan 8, 2025
52c1b2b
Add default destination path for sass.mjs
Skrypt Jan 8, 2025
2995718
Null check on asset group name
Skrypt Jan 8, 2025
e53a7ac
Remove root package-lock.json file
Skrypt Jan 8, 2025
68c8202
Merge branch 'main' into skrypt/asset-build-tool
Skrypt Jan 8, 2025
074da60
Upgrade build tool dependencies
Skrypt Jan 8, 2025
e3d4cbf
OrchardCore.Resources move to new Assets.json
Skrypt Jan 8, 2025
10187bb
Add retry logic to Concurrently
Skrypt Jan 8, 2025
fd7c476
update yarn.lock
Skrypt Jan 8, 2025
7b19fe8
Migrate OrchardCore.Resources assets
Skrypt Jan 8, 2025
0422ac6
Revert rename assets.json files
Skrypt Jan 9, 2025
3042b25
WIP Migrate to Assets2.json
Skrypt Jan 9, 2025
2fc2e86
Default to /wwwroot/Scripts
Skrypt Jan 9, 2025
10976af
Rename folder with Uppercase
Skrypt Jan 9, 2025
2f47d39
Update tags
Skrypt Jan 9, 2025
e7c1afc
Add \r\n on map EOF
Skrypt Jan 9, 2025
9048f64
test
Skrypt Jan 9, 2025
f78da9c
use \n
Skrypt Jan 9, 2025
142db4e
Remove folder
Skrypt Jan 9, 2025
4795c60
Add back folder
Skrypt Jan 9, 2025
ce09ff9
use \n in source map files
Skrypt Jan 9, 2025
c5a0eac
replace crlf with lf
Skrypt Jan 9, 2025
8ea0719
use gitattributes for eol
Skrypt Jan 9, 2025
ef59521
Update .gitattributes
Skrypt Jan 9, 2025
79a4125
update map files
Skrypt Jan 9, 2025
5192ddb
Merge branch 'skrypt/asset-build-tool' of https://github.com/OrchardC…
Skrypt Jan 9, 2025
23792df
update gitattributes
Skrypt Jan 9, 2025
9878aea
remove
Skrypt Jan 9, 2025
e8c9414
add back
Skrypt Jan 9, 2025
da4b149
add back gitatt
Skrypt Jan 9, 2025
cfa3af3
gitatt
Skrypt Jan 9, 2025
eaf8237
gitatt
Skrypt Jan 9, 2025
23650c7
rem
Skrypt Jan 9, 2025
627c918
add
Skrypt Jan 9, 2025
6ebac66
Migrate some themes
Skrypt Jan 10, 2025
743f9ba
Merge branch 'main' into skrypt/asset-build-tool
Skrypt Jan 10, 2025
5d4a1eb
Adding PostCSS-LTR
Skrypt Jan 10, 2025
86948be
fix
Skrypt Jan 10, 2025
3999163
Fix again
Skrypt Jan 10, 2025
782a8a2
fix js map
Skrypt Jan 10, 2025
6071ac5
update from linux
Skrypt Jan 11, 2025
7b3d8ea
Refactor OC.Setup with Typescript
Skrypt Jan 11, 2025
f4adea5
More migration to Asset2
Skrypt Jan 11, 2025
dbfe1a9
Format .cshtml
Skrypt Jan 11, 2025
42f5c7a
Update workspaces
Skrypt Jan 11, 2025
bdb9cfa
Add common frontend workspace
Skrypt Jan 11, 2025
9f5d234
Rename to password-strenght.ts
Skrypt Jan 11, 2025
8d56b55
Migrate OC.Themes
Skrypt Jan 11, 2025
0021d56
WIP migration
Skrypt Jan 17, 2025
803bf7e
WIP ts migration
Skrypt Jan 21, 2025
a86a5a8
Merge branch 'main' into skrypt/asset-build-tool
Skrypt Jan 21, 2025
578d1cb
Fix Media Gallery not displaying
Skrypt Jan 21, 2025
1c25005
Remove .map files
Skrypt Jan 21, 2025
9a5c043
.map only on development
Skrypt Jan 21, 2025
2e075c6
Remove
Skrypt Jan 21, 2025
cde492c
fix build
Skrypt Jan 21, 2025
2835695
Fix Media app
Skrypt Jan 21, 2025
6aacce9
Fix File App
Skrypt Jan 21, 2025
cad3e54
Migrate OrchardCore.Workflows
Skrypt Jan 21, 2025
6d8e081
Move package.json, remove lock
Skrypt Jan 21, 2025
7b09bce
Remove package-lock.json files
Skrypt Jan 21, 2025
7c13411
remove workspaces globs
Skrypt Jan 25, 2025
35a108e
Add watcher on sass action
Skrypt Jan 25, 2025
df9c4ab
use GulpAssets.json and Assets.json
Skrypt Jan 25, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion .gitattributes
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
* text=auto

*.map text eol=lf
Skrypt marked this conversation as resolved.
Show resolved Hide resolved
**/wwwroot/Scripts/* linguist-vendored
6 changes: 4 additions & 2 deletions .github/workflows/assets_validation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ jobs:
- uses: actions/checkout@v4
- name: Rebuild packages
run: |
npm install
gulp rebuild
npm install -g corepack
corepack enable
yarn install
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be a devDependency in a package.json? That way, Renovate could update it, and we'd use an explicit version too. This can break our build if the version changes.

yarn build -gr
- name: Check if git has changes
shell: pwsh
run: |
Expand Down
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,15 @@ nuget.exe
#exclude node modules
node_modules/

#exclude yarn
.yarn

#exclude parcel
.parcel-cache

#exclude .map files
*.map

wwwroot
**/Localization/**/*.po
!test/OrchardCore.Tests/Localization/**/*.po
Expand Down
1 change: 1 addition & 0 deletions .scripts/assets-build-tool/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
dist
7 changes: 7 additions & 0 deletions .scripts/assets-build-tool/.parcelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"extends": "@parcel/config-default",
"resolvers": ["@parcel/resolver-glob", "..."],
"optimizers": {
"*.{js,mjs,cjs}": ["@parcel/optimizer-terser"]
}
}
227 changes: 227 additions & 0 deletions .scripts/assets-build-tool/Readme.md
Skrypt marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
# Assets build tools

Assets build scripts. The process uses a `Assets.json` file that defines actions to take relating to static assets.

## Random Notes

- The copy task does not watch for file changes and the watch commands do not copy files. The build command will copy files.
- Use dry-run to see a log of which files are being copied and which asset files we have in the solution.
- Parcel seems a bit picky with transpiling some libraries(azure-maps-control for example)

## Supported actions

### Parcel

Runs the Parcel bundler.

**Note**: Sometimes, Parcel is too aggressive in its caching. If you manually delete any output folders, you may need to delete the `.parcel-cache` folder as well for Parcel to write to it again. Running the `yarn clean` command will clean it up for you.

```json
[
{
"action": "parcel",
"name": "module-microsoft-datasource-wrapper",
"source": "Assets/Scripts/datasource-wrapper.js",
"dest": "wwwroot/datasource-wrapper",
"tags":["vue3"]
}
]
```

The `source` property must be the entry point passed to the parcel bundler.
The `dest` property must be a folder. This is because parcel will usually output multiple files.
The `tags` property can be a string or an array of strings.
You can also pass an `options` object that override parcel options.

### Run

Allows to run a command.

```json
[
{
"action": "run",
"name": "itwin-viewer-app",
"source": "Assets/itwin-viewer-app",
"scripts": {
"build": "yarn run build",
"watch": "yarn run start"
}
}
]
```

Here, the `source` property must be a folder and is used as the working directory where the command is ran.
The scripts keys must match the command used to start the pipeline. If you start the pipeline with `yarn build` this would run all `build` scripts of the run actions.

### Copy

Allows to copy files.

```json
[
{
"action": "copy",
"dryRun": true,
"name": "copy-bootstrap-js",
"source": "node_modules/bootstrap/dist/js/*.js*",
"dest": "wwwroot/Scripts"
},
{
"action": "copy",
"name": "copy-bootstrap-css",
"source": "node_modules/bootstrap/dist/css/*.css*",
"dest": "wwwroot/Styles"
}
]
```

The source field can be a file, or a glob of files.
The destination should always be a folder as we do not support renaming files.
You can use the dry-run task to log to the console where the files will be copied to.

### Min

Allows to minify files.

```json
[
{
"action": "min",
"dryRun": true,
"name": "copy-bootstrap-js",
"source": "node_modules/bootstrap/dist/js/*.js*",
"dest": "wwwroot/Scripts"
},
{
"action": "min",
"name": "copy-bootstrap-css",
"source": "node_modules/bootstrap/dist/css/*.css*",
"dest": "wwwroot/Styles"
}
]
```

The source field can be a file, or a glob of files.
The destination should always be a folder as we do not support renaming files.
You can use the dry-run task to log to the console where the files will be copied to.

### Sass

Allows to transpile scss files.

```json
[
{
"action": "sass",
"name": "transpile-bootstrap-scss",
"source": "node_modules/bootstrap/dist/css/main.scss",
"dest": "wwwroot/Styles"
}
]
```

The source field can be a file, or a glob of files.
The destination should always be a folder as we do not support renaming files.
You can use the dry-run task to log to the console where the files will be copied to.

## build.config.mjs

You can create a `build.config.mjs` file next to the root `package.json`.
This file allows you to customize options used by the build tools.

For example, if you wanted to override the parcel browserlist:

```javascript
// The type of command running and the current group's json object.
export function parcel(type, group) {
return {
defaultTargetOptions: {
engines: {
browsers: "> 1%, last 4 versions, not dead",
},
},
};
}
```

Here is an example for vite:

```javascript
import vue from "@vitejs/plugin-vue";
export function viteConfig(action) {
return {
plugins: [vue()],
build: {
minify: false,
rollupOptions: {
output: {
manualChunks: (id) => {
if (id.includes("node_modules")) {
if (id.includes("@vue") || id.includes("/vue/")) {
return "vue";
}
return "vendor"; // all other package goes here
}
},
},
},
},
};
}
```

You can also specify the glob pattern used to harvest the `Assets.json` files in your solution in the build.config.mjs file

```javascript
export const assetsLookupGlob = "src/{OrchardCore.Modules,OrchardCore.Themes}/*/Assets.json";
```

## ECMAScript vs CommonJS (Parcel and Vite)

The ECMAScript module (ESM) format is the standardized way of loading JavaScript packages.
CommonJS is a legacy implementation of modules that is not standardized.
ESM is asynchronously loaded, while CommonJS is synchronous.
We should favorize building as ESM modules.

Vite ([rollup.js](https://rollupjs.org/)) will build by default as ECMAScripts and it is by design.
Parcel will automatically build as CommonJS or ECMAScript based on package.json configuration;
CommonJS being the default when the "type" parameter is not specified.

To be able to compile as ECMAScript there are requirements.

1 - the package.json file needs to have:

```json
{
"type": "module",
}
```

This should be enough for any single script files that we want to execute asynchronously.

Though, for Vue 3 apps to use ECMAScript; it needs to use an alias to its ESM bundler version to prevent needing it everywhere in the different components of the app.

```javascript
import { createApp } from 'vue' //needs an alias to 'vue/dist/vue.esm-bundler.js'
```

Example for an app that will use Vite/TS would be to add this configuration to a vite.config.ts file.

```json
resolve: {
alias: {
'vue': 'vue/dist/vue.esm-bundler.js',
},
},
```

Also, now when adding a `<script>` tag to the HTML you will need to use:

```html
<script type="module" src="somepath"></script>
```

`<script>` tags are non-ESM by default; you have to add a `type="module"` attribute to opt into ESM mode.
Meaning that the ESM script will be interpreted as CommonJS by the browser if the script tag doesn't have it.
Also, Vite builds currently will return a console log if you are trying to use them without the `type="module"` parameter on a script tag if not they will throw exceptions from code, so it is mandatory to use `type="module"` with them. Parcel doesn't prevent this and their ESM compiled script will load fine but you should try to avoid it else it is counter productive, you should then use a CommonJS build.
44 changes: 44 additions & 0 deletions .scripts/assets-build-tool/assetGroups.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { glob } from 'glob'
import JSON5 from "json5";
import fs from "fs-extra";
import path from "path";

import buildConfig from "./config.mjs";

// get's an object representation of all Assets.json in the solution
export default function getAllAssetGroups() {
var assetGroups = [];
getAssetsJsonPaths().forEach(function (assetManifestPath) {
var assetManifest = JSON5.parse(fs.readFileSync(assetManifestPath, "utf-8"));
assetManifest.forEach(function (assetGroup) {
resolveAssetGroupPaths(assetGroup, assetManifestPath);
assetGroups.push(assetGroup);
});
});
return assetGroups;
}

// Expands the paths to full paths.
function resolveAssetGroupPaths(assetGroup, assetManifestPath) {
assetGroup.manifestPath = assetManifestPath;
assetGroup.basePath = path.dirname(assetManifestPath);
if (assetGroup.source) {
assetGroup.originalSource = assetGroup.source;
// since node_modules all resolve at the root (because of yarn)
if (assetGroup.source.startsWith("node_modules")) {
assetGroup.source = path.resolve(path.join(process.cwd(), assetGroup.source)).replace(/\\/g, "/");
} else {
assetGroup.source = path.resolve(path.join(assetGroup.basePath, assetGroup.source)).replace(/\\/g, "/");
}
// The source path relative to the root of the solution.
assetGroup.relativeSource = assetGroup.source.substring(process.cwd().length);

}
if (assetGroup.dest) {
assetGroup.dest = path.resolve(path.join(assetGroup.basePath, assetGroup.dest)).replace(/\\/g, "/");
}
}

function getAssetsJsonPaths() {
return glob.sync(buildConfig("assetsLookupGlob"), {});
}
Loading