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

Doc update #202

Merged
merged 7 commits into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions docs/_data/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@
"title": "Merkur widget as custom element",
"url": "/docs/register-custom-element"
},
{
"title": "CLI",
"url": "/docs/merkur-cli"
},
{
"title": "Merkur config file",
"url": "/docs/merkur-config"
},
{
"title": "Plugins",
"url": "/docs/plugins"
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ The package.json contains predefined dependencies and defines some scripts, whic

### merkur.config.mjs

The configuration file for Merkur [CLI]({{ '/docs/merkur-cli' | relative_url }})
The [configuration file]({{ '/docs/merkur-config' | relative_url }}) for Merkur [CLI]({{ '/docs/merkur-cli' | relative_url }})

### src

Expand Down
17 changes: 17 additions & 0 deletions docs/docs/integration-with-app.md
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,23 @@ Below you can see visualization of how the react component handles synchronizati
<img class="responsive" src="{{ '/assets/images/merkur-integration-lifecycle.png?v=' | append: site.github.build_revision | relative_url }}" alt="Merkur - integration React - lifecycle methods" />
</a>

If you have some problems with integration you can turn on debug mode which can be helpful for solving your problems.

```jsx
return (
<MerkurWidget
debug={true}
widgetProperties={widgetProperties}
onWidgetMounted={widget => this._widgetMounted()}
onWidgetUnmouting={widget => this._widgetUnmounting()}
onError={error => this._handleError(error)}>
<div>
Fallback for undefined widgetProperties
</div>
</MerkurWidget>
);
```


### Slots

Expand Down
83 changes: 7 additions & 76 deletions docs/docs/merkur-cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,85 +5,16 @@ title: Merkur CLI

# Merkur CLI

Merkur CLI for building your widget use [esbuild](https://esbuild.github.io/) tool which improve performance of development process and build tasks over [webpack](https://webpack.js.org/). The merkur CLi is configurable with `merkur.config.mjs` file which is in root of your project.

The full merkur config can be look like:

```javascript
/**
* @type import('@merkur/cli').defineConfig
*/
export default function ({ cliConfig, emitter, }) {
return {
extends: [ '@merkur/preact/cli' ], // Merkur predefined extender
task: { // defined tasks to building your widget, default are node, es13 and es9
node: {
name: 'node',
build: ESBuildConfiguration, // https://esbuild.github.io/api/#build
}
es13: {
name: 'es13',
build: ESBuildConfiguration, // https://esbuild.github.io/api/#build
}
es9: {
name: 'es9',
build: ESBuildConfiguration, // https://esbuild.github.io/api/#build
}
},
devServer: { // configuration for Merkur dev server
protocol: 'http:',
host: 'localhost:4445',
port: 4445,
staticPath: '/static',
staticFolder: '{project_folder}/build/static',
origin: 'http://localhost:4445'
},
defaultEntries: {
// entries for your project, you can override it with creating /src/entries/{client|server.js} file
client: [
'{project_folder}/node_modules/@merkur/preact/entries/client.js'
],
server: [
'{project_folder}/node_modules/@merkur/preact/entries/server.js'
]
},
playground: {
template: '{project_folder}/node_modules/@merkur/cli/src/templates/playground.ejs',
templateFolder: '{project_folder}/node_modules/@merkur/cli/src/templates',
path: '/',
widgetHandler: AsyncFunction,
widgetParams: Function,
},
socketServer: {
protocol: 'ws:',
host: 'localhost:4321',
port: 4321
},
widgetServer: { // configuration for Merkur widget production server
protocol: 'http:',
host: 'localhost:4444',
port: 4444,
staticPath: '/static',
staticFolder: '{project_folder}/build/static',
buildFolder: '{project_folder}/build',
clusters: 3,
origin: 'http://localhost:4444'
},
HMR: true,
constant: {
HOST: 'localhost',
}
onCliConfig, Function, //extending hook for cli config,
onMerkurConfig: Function, // extending hook for merkur config,
onTaskConfig: Function, // extending hook for task config,
onTaskBuild, Function, // extending hook esbuild config
};
}
```
Merkur CLI for building your widget use [esbuild](https://esbuild.github.io/) tool which improve performance of development process and build tasks over [webpack](https://webpack.js.org/). The merkur CLi is configurable with [merkur.config.mjs]({{ '/docs/merkur-config' | relative_url }}) file which is in root of your project.

## Commands

- `merkur dev` - build your widget with with NODE_ENV = 'development' and with watch mode
- `merkur build` - build your widget with NODE_ENV = 'production'
- `merkur test` - run defined widget tests with NODE_ENV = 'test'
- `merkur start` - run widget server and playground server
- `merkur start` - run widget server and playground server
- `merkur custom` - customize part of template (playground page)

## Custom playground template

At first run `merkur custom playground:body` command which create `body.ejs` file in your project in `/server/playground/templates` folder. Now you can modify playground page as you wish.
253 changes: 253 additions & 0 deletions docs/docs/merkur-config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
---
layout: docs
title: Merkur config
---

# Merkur config

The `merkur.config.mjs` file is main configuration file for Merkur [CLI]({{ '/docs/merkur-cli' | relative_url }}) and your project.

The full merkur config can be look like:

```javascript
/**
* @type import('@merkur/cli').defineConfig
*/
export default function ({ cliConfig, emitter, }) {
return {
extends: [ '@merkur/preact/cli' ], // Merkur predefined extender
task: { // defined tasks to building your widget, default are node, es13 and es9
node: {
name: 'node',
build: ESBuildConfiguration, // https://esbuild.github.io/api/#build
}
es13: {
name: 'es13',
folder: 'es13',
build: ESBuildConfiguration, // https://esbuild.github.io/api/#build
}
es9: {
name: 'es9',
folder: 'es9',
build: ESBuildConfiguration, // https://esbuild.github.io/api/#build
}
},
devServer: { // configuration for Merkur dev server
protocol: 'http:',
host: 'localhost:4445',
port: 4445,
staticPath: '/static',
staticFolder: '{project_folder}/build/static',
origin: 'http://localhost:4445'
},
defaultEntries: {
// entries for your project, you can override it with creating /src/entries/{client|server.js} file
client: [
'{project_folder}/node_modules/@merkur/preact/entries/client.js'
],
server: [
'{project_folder}/node_modules/@merkur/preact/entries/server.js'
]
},
playground: {
template: '{project_folder}/node_modules/@merkur/cli/src/templates/playground.ejs',
templateFolder: '{project_folder}/node_modules/@merkur/cli/src/templates',
serverTemplateFolder: '{project_folder}/server/playground/templates',
path: '/',
widgetHandler: AsyncFunction,
widgetParams: Function,
},
socketServer: {
protocol: 'ws:',
host: 'localhost:4321',
port: 4321
},
widgetServer: { // configuration for Merkur widget production server
protocol: 'http:',
host: 'localhost:4444',
port: 4444,
staticPath: '/static',
staticFolder: '{project_folder}/build/static',
buildFolder: '{project_folder}/build',
clusters: 3,
origin: 'http://localhost:4444'
},
HMR: true,
constant: {
HOST: 'localhost',
}
onCliConfig, Function, //extending hook for cli config,
onMerkurConfig: Function, // extending hook for merkur config,
onTaskConfig: Function, // extending hook for task config,
onTaskBuild, Function, // extending hook esbuild config
};
}
```

## How to define custom task

For example we create custom task for bundling ES11 version of Merkur widget very simple.

```javascript
/**
* @type import('@merkur/cli').defineConfig
*/
export default function ({ cliConfig, emitter, }) {
return {
task: {
es11: {
name: 'es11',
folder: 'es11',
build: { // ESBuildConfiguration option
platform: 'browser',
target: 'es2020',
outdir: `${cliConfig.staticFolder}/es11`
}
}
},
};
}
```

Or If you want to bundle Merkur widget and some JS asset for your Merkur widget with own entry point. You can use Merkur [CLI]({{ '/docs/merkur-cli' | relative_url }}) to define custom tasks for that asset. For example:

```javascript
/**
* @type import('@merkur/cli').defineConfig
*/
export default function ({ cliConfig, emitter, }) {
return {
task: {
es13Asset: {
name: 'es13Asset',
folder: 'es13',
build: {
entryPoints: `${cliConfig.projectFolder}/src/customAsset.js`,
entryNames: !cliConfig.isProduction ? 'customAsset' : 'customAsset.[hash]',
platform: 'browser',
outdir: `${staticFolder}/es13`,
plugins: merkurConfig.task['es13'].build.plugins,
},
},
es9Asset: {
name: 'es9Asset',
folder: 'es9',
build: {
entryPoints: `${cliConfig.projectFolder}/src/customAsset.js`,
entryNames: !cliConfig.isProduction ? 'customAsset' : 'customAsset.[hash]',
platform: 'browser',
target: 'es2018',
outdir: `${staticFolder}/es9`,
plugins: merkurConfig.task['es9'].build.plugins,
},
}
},
onCliConfig({ cliConfig }) {
// add es13Asset task to be run for `merkur dev`
if (cliConfig.command === 'dev') {
cliConfig.runTask.push('es13Asset');
}
},
};
}
```

## How to add esbuild plugin

By default Merkur [CLI]({{ '/docs/merkur-cli' | relative_url }}) as esbuild load only css files. If you want to use some css preprocessors like `less` or others. You must install esbuild plugin for that with `npm install esbuild-plugin-less --save dev` command. Then add new installed package in `merkur.config.js` to [esbuild](https://esbuild.github.io/) configuration.

```javascript
/**
* @type import('@merkur/cli').defineConfig
*/
export default function ({ cliConfig, emitter, }) {
const loaders = [];

try {
const { lessLoader } = await import('esbuild-plugin-less');

loaders.push(
lessLoader({})
);
} catch {
// Fail silently
}

return {
onTaskBuild({ build }) {
build.plugins.push(...loaders);

return build;
},
};
}
```
The `esbuild-plugin-*` must be dynamic imported with `try/catch` block because `merkur.config.js` is used for all Merkur [CLI]({{ '/docs/merkur-cli' | relative_url }}) commands and of course for `merkur start` where dev dependencies can be missed. It depends on your CI/CD workflow. But we predict that you run `merkur start` command only with production dependencies where dev dependencies miss.

Or you want to use [Tailwind CSS](https://tailwindui.com/) framework. You must install esbuild plugin with `npm install esbuild-plugin-tailwindcss --save dev` command. Then add new installed package in `merkur.config.js` to [esbuild](https://esbuild.github.io/) configuration.

```javascript
/**
* @type import('@merkur/cli').defineConfig
*/
export default function ({ cliConfig, emitter, }) {
const loaders = [];

try {
const { tailwindPlugin } = await import('esbuild-plugin-tailwindcss');

loaders.push(
tailwindPlugin({})
);
} catch {
// Fail silently
}

return {
onTaskBuild({ build }) {
build.plugins.push(...loaders);

return build;
},
};
}
```

You must create file `tailwind.config.js` at the root of the project.

```javascript
// ./tailwind.config.js
export default {
content: ['./src/**/*.{js,jsx,ts,tsx}'],
// For more, see: https://tailwindcss.com/docs/configuration
};
```

You must create file index.css and import index.css file to `./src/widget.js`.

```css
/* ./src/style.css */
@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';
```

## How to override playground widgetParams to widget API

By default playground page pass all route query params to widgetParams. If you want to modify that logic which can be helpful for example with `@merkur/plugin-router` which route defined routes by `pathname` then is useful set widgetParams `pathname` to `req.path`. You can also reconfigure regular `path` for playground page for which playground page works.

```javascript
/**
* @type import('@merkur/cli').defineConfig
*/
export default function ({ cliConfig, emitter, }) {
return {
playground: {
widgetParams: req => {
return new URLSearchParams({ pathname: req.path });
},
path: /(\/$|\/some-folder\/.*)/g
}
}
}
```
Loading