-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add a shared Rsbuild configuration to build cozy application
- Loading branch information
Showing
7 changed files
with
1,400 additions
and
67 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
MIT License | ||
|
||
Copyright (c) 2017-present, Cozy Cloud | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
<h1 align="center">Rsbuild Config Cozy App</h1> | ||
|
||
## Migrating from cozy-scripts | ||
|
||
### Install dependencies | ||
|
||
Run the following command to install the necessary dependencies: | ||
```bash | ||
yarn add @rsbuild/core rsbuild-config-cozy-app --dev | ||
``` | ||
|
||
### Create a configuration file | ||
|
||
Create a file named `rsbuild.config.mjs` in your project directory with the following content: | ||
```javascript | ||
import { defineConfig } from '@rsbuild/core' | ||
import { getRsbuildConfig } from 'rsbuild-config-cozy-app' | ||
|
||
const config = getRsbuildConfig({ | ||
title: 'Your application name', | ||
hasServices: true | ||
}) | ||
|
||
export default defineConfig(config) | ||
``` | ||
|
||
### Update Scripts in package.json | ||
|
||
Modify the `scripts` section in your `package.json` file as follows: | ||
```json | ||
"scripts": { | ||
"build": "rsbuild build", | ||
"watch": "rsbuild build --watch", | ||
"analyze": "RSDOCTOR=true yarn build" | ||
} | ||
``` | ||
|
||
### Migrate Assets | ||
|
||
Move assets that are not used in the React build to the `/public` directory. This directory will be copied to a public folder. For example, move assets from `/src/targets/vendor/assets` to `/public`. Ensure the `/public` directory exists. By default, Rsbuild copies the content of the public directory to the `distPath`. To comply with cozy-stack constraints, disable this behavior and copy the public directory to a separate folder called `assets` so it can be shared between public and private. | ||
|
||
### Update index.ejs | ||
|
||
Remove all references to webpack in your `index.ejs` file. Here is an example of an updated `index.ejs`: | ||
```html | ||
<!DOCTYPE html> | ||
<html lang="{{.Locale}}"> | ||
<head> | ||
<meta charset="utf-8"> | ||
<title><%= htmlPlugin.options.title %></title> | ||
<link rel="apple-touch-icon" sizes="180x180" href="/assets/apple-touch-icon.png"> | ||
<link rel="icon" type="image/png" href="/assets/favicon-32x32.png" sizes="32x32"> | ||
<link rel="icon" type="image/png" href="/assets/favicon-16x16.png" sizes="16x16"> | ||
<link rel="manifest" href="/assets/manifest.json" crossorigin="use-credentials"> | ||
<link rel="mask-icon" href="/assets/safari-pinned-tab.svg" color="#297EF2"> | ||
<meta name="color-scheme" content="light dark" /> | ||
<meta name="theme-color" content="#ffffff"> | ||
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1, viewport-fit=cover"> | ||
<link rel="stylesheet" type="text/css" href="//{{.Domain}}/assets/fonts/fonts.css"> | ||
{{.ThemeCSS}} | ||
</head> | ||
<body> | ||
<div role="application" data-cozy="{{.CozyData}}"></div> | ||
</body> | ||
</html> | ||
``` | ||
|
||
### Step-by-Step Changes | ||
|
||
1. Change `<title><%= htmlWebpackPlugin.options.title %></title>` to `<title><%= htmlPlugin.options.title %></title>`. | ||
2. Remove `_.forEach` for importing CSS and JS files, as RSBuild handles this directly. | ||
3. Import fonts using `<link rel="stylesheet" type="text/css" href="//{{.Domain}}/assets/fonts/fonts.css">`. | ||
4. Prefix assets import with `/assets` | ||
|
||
### Define Aliases | ||
|
||
Ensure all aliases are defined in the `tsconfig.json`. | ||
|
||
### Handling public targets | ||
|
||
If your app have a public target, you need to declare the assets as public route inside your manifest.webapp : | ||
```javascript | ||
"/assets": { | ||
"folder": "/assets", | ||
"public": true | ||
} | ||
``` | ||
**Note :** You can found more info into the cozy-stack [documentation](https://github.com/cozy/cozy-stack/blob/2cbb312271732663e18802079870747e3a03d03e/docs/apps.md?plain=1#L51) | ||
|
||
## Best Practices | ||
|
||
- Keep file extensions, especially for `.styl` files. | ||
- Place any files that need to be included in the build package but are not used in React inside the root `public` folder. These files will be copied to the public folder, avoiding duplicated assets for public builds. | ||
- Use a general alias like `@/`. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,183 @@ | ||
import fs from 'fs' | ||
import path from 'path' | ||
|
||
import { pluginNodePolyfill } from '@rsbuild/plugin-node-polyfill' | ||
import { pluginReact } from '@rsbuild/plugin-react' | ||
import { pluginStylus } from '@rsbuild/plugin-stylus' | ||
import { RsdoctorRspackPlugin } from '@rsdoctor/rspack-plugin' | ||
import { pluginEjs } from 'rsbuild-plugin-ejs' | ||
|
||
import { getServicesEntries } from './helpers' | ||
|
||
/** | ||
* Generates the configuration object for the Rsbuild tool. | ||
* | ||
* @param {Object} options - The options object. | ||
* @param {string} options.title - The title of the app. | ||
* @param {boolean} [options.hasPublic] - Indicates if the app has a public target. | ||
* @param {boolean} [options.hasServices] - Indicates if the app has services target. | ||
* @param {boolean} [options.hasIntents] - Indicates if the app has a intents target. | ||
* @returns {Object} The configuration object for Rsbuild. | ||
*/ | ||
function getRsbuildConfig({ | ||
hasServices = false, | ||
hasPublic = false, | ||
hasIntents = false, | ||
title | ||
} = {}) { | ||
const appPath = fs.realpathSync(process.cwd()) | ||
|
||
return { | ||
plugins: [ | ||
pluginEjs(), | ||
pluginNodePolyfill(), | ||
pluginReact(), | ||
pluginStylus({ | ||
stylusOptions: { | ||
// To resolve import from cozy-ui inside stylus files | ||
paths: [path.resolve(appPath, 'node_modules', 'cozy-ui', 'stylus')] | ||
} | ||
}) | ||
], | ||
output: { | ||
cleanDistPath: true, | ||
filename: { | ||
html: 'index.html' | ||
}, | ||
cssModules: { | ||
// By default, only .module.styl files are considered as CSS modules by Rsbuild. | ||
// This option forces all .styl files to be resolved as CSS modules. | ||
auto: resource => resource.endsWith('.styl') | ||
} | ||
}, | ||
performance: { | ||
chunkSplit: { | ||
forceSplitting: { | ||
cozy: /node_modules[\\/]cozy*/ | ||
} | ||
} | ||
}, | ||
html: { | ||
title | ||
}, | ||
tools: { | ||
rspack: { | ||
module: { | ||
rules: [ | ||
{ | ||
test: /\.webapp$/i, | ||
type: 'json' | ||
} | ||
] | ||
}, | ||
plugins: [ | ||
// Only register the plugin when RSDOCTOR is true, as the plugin will increase the build time. | ||
process.env.RSDOCTOR && new RsdoctorRspackPlugin() | ||
].filter(Boolean) | ||
} | ||
}, | ||
server: { | ||
publicDir: { | ||
copyOnBuild: false | ||
} | ||
}, | ||
environments: { | ||
main: { | ||
html: { | ||
template: './src/targets/browser/index.ejs' | ||
}, | ||
source: { | ||
entry: { | ||
main: './src/targets/browser/index.jsx' | ||
} | ||
}, | ||
output: { | ||
target: 'web', | ||
distPath: { | ||
root: 'build' | ||
}, | ||
copy: [ | ||
{ | ||
from: 'manifest.webapp' | ||
}, | ||
{ | ||
from: 'README.md' | ||
}, | ||
{ | ||
from: 'LICENSE' | ||
}, | ||
{ | ||
from: 'public', | ||
to: 'assets' | ||
} | ||
] | ||
} | ||
}, | ||
...(hasPublic && { | ||
public: { | ||
html: { | ||
template: './src/targets/public/index.ejs' | ||
}, | ||
source: { | ||
entry: { | ||
public: './src/targets/public/index.jsx' | ||
} | ||
}, | ||
output: { | ||
target: 'web', | ||
distPath: { | ||
root: 'build/public' | ||
}, | ||
assetPrefix: '/public' | ||
} | ||
} | ||
}), | ||
...(hasIntents && { | ||
intents: { | ||
html: { | ||
template: './src/targets/intents/index.ejs' | ||
}, | ||
source: { | ||
entry: { | ||
intents: './src/targets/intents/index.jsx' | ||
} | ||
}, | ||
output: { | ||
target: 'web', | ||
distPath: { | ||
root: 'build/intents' | ||
}, | ||
assetPrefix: '/intents' | ||
} | ||
} | ||
}), | ||
...(hasServices && { | ||
services: { | ||
source: { | ||
entry: getServicesEntries(appPath) | ||
}, | ||
output: { | ||
target: 'node', | ||
distPath: { | ||
root: 'build/services' | ||
} | ||
}, | ||
tools: { | ||
rspack: { | ||
module: { | ||
rules: [ | ||
{ | ||
test: /\.hbs$/, // Only for services with notification | ||
type: 'asset/source' | ||
} | ||
] | ||
} | ||
} | ||
} | ||
} | ||
}) | ||
} | ||
} | ||
} | ||
|
||
export { getRsbuildConfig } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import fs from 'fs' | ||
import path from 'path' | ||
|
||
/** | ||
* Retrieves the entries for services target in the specified application path. | ||
* | ||
* This function reads the contents of the 'src/targets/services' directory within the given application path, | ||
* filters for JavaScript (.js) and TypeScript (.ts) files, and returns an object mapping each service name | ||
* (derived from the file name) to its relative path. | ||
* | ||
* Example: | ||
* ``` | ||
* { | ||
* service1: 'src/targets/services/service1.js', | ||
* service2: 'src/targets/services/service2.ts' | ||
* } | ||
* ``` | ||
* @param {string} appPath - The root path of the application. | ||
* @returns {Object} An object where the keys are service names and the values are the relative paths to the service files. | ||
*/ | ||
export const getServicesEntries = appPath => { | ||
const servicesDir = path.resolve(appPath, 'src', 'targets', 'services') | ||
|
||
return fs | ||
.readdirSync(servicesDir) | ||
.filter(file => file.endsWith('.js') || file.endsWith('.ts')) | ||
.reduce( | ||
(current, file) => ({ | ||
...current, | ||
[file.slice(0, -3)]: `./src/targets/services/${file}` | ||
}), | ||
{} | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { getRsbuildConfig } from './getRsbuildConfig' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
{ | ||
"name": "rsbuild-config-cozy-app", | ||
"version": "0.0.0", | ||
"description": "Rsbuild config for Cozy Application (Cozy Cloud)", | ||
"author": "Cozy Cloud", | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/cozy/cozy-libs.git" | ||
}, | ||
"homepage": "https://github.com/cozy/cozy-libs/tree/master/packages/rsbuild-config-cozy-app", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/cozy/cozy-libs/issues" | ||
}, | ||
"files": [ | ||
"index.js", | ||
"getRsbuildConfig.js" | ||
], | ||
"devDependencies": { | ||
"@rsbuild/core": "1.1.2", | ||
"cozy-ui": "113.2.0" | ||
}, | ||
"dependencies": { | ||
"@rsbuild/plugin-node-polyfill": "1.2.0", | ||
"@rsbuild/plugin-react": "1.0.7", | ||
"@rsbuild/plugin-stylus": "^1.0.6", | ||
"@rsdoctor/rspack-plugin": "^0.4.8", | ||
"rsbuild-plugin-ejs": "1.0.1" | ||
}, | ||
"peerDependencies": { | ||
"@rsbuild/core": ">= 1.1.2", | ||
"cozy-ui": ">= 113.2.0" | ||
} | ||
} |
Oops, something went wrong.