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

feat(core): merge all client files hook into clientConfigFile #888

Merged
merged 6 commits into from
May 14, 2022
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
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ module.exports = {
},
},
{
files: ['clientAppEnhance.ts'],
files: ['**/client/config.ts'],
rules: {
'vue/match-component-file-name': 'off',
},
Expand Down
2 changes: 1 addition & 1 deletion docs/.vuepress/configs/sidebar/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const en: SidebarConfig = {
text: 'Cookbook',
children: [
'/advanced/cookbook/README.md',
'/advanced/cookbook/usage-of-client-app-enhance.md',
'/advanced/cookbook/usage-of-client-config.md',
'/advanced/cookbook/adding-extra-pages.md',
'/advanced/cookbook/making-a-theme-extendable.md',
'/advanced/cookbook/passing-data-to-client-code.md',
Expand Down
2 changes: 1 addition & 1 deletion docs/.vuepress/configs/sidebar/zh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const zh: SidebarConfig = {
text: 'Cookbook',
children: [
'/zh/advanced/cookbook/README.md',
'/zh/advanced/cookbook/usage-of-client-app-enhance.md',
'/zh/advanced/cookbook/usage-of-client-config.md',
'/zh/advanced/cookbook/adding-extra-pages.md',
'/zh/advanced/cookbook/making-a-theme-extendable.md',
'/zh/advanced/cookbook/passing-data-to-client-code.md',
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/.vuepress/public/images/guide/vuepress-core-process.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
87 changes: 0 additions & 87 deletions docs/advanced/cookbook/usage-of-client-app-enhance.md

This file was deleted.

156 changes: 156 additions & 0 deletions docs/advanced/cookbook/usage-of-client-config.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
# Usage of Client Config

You can make use of the [client config file](../../guide/configuration.md#client-config-file) directly in your project, or specify the file path in your plugin or theme via [clientConfigFile](../../reference/plugin-api.md#clientconfigfile) hook:

```ts
import { path } from '@vuepress/utils'

const pluginOrTheme = {
clientConfigFile: path.resolve(__dirname, './path/to/clientConfig.ts'),
}
```

Inside the client config file, `@vuepress/client` package provides a helper function [defineClientConfig](../../reference/client-api.md#defineclientconfig) to help you define the client config:

```ts
import { defineClientConfig } from '@vuepress/client'

export default defineClientConfig({
enhance({ app, router, siteData }){},
setup(){},
rootComponents: [],
})
```

## enhance

The `enhance` function could be either synchronous or asynchronous. It accepts a context param with following properties:

- `app` is the Vue application instance that created by [createApp](https://vuejs.org/api/application.html#createapp).
- `router` is the Vue Router instance that created by [createRouter](https://router.vuejs.org/api/#createrouter).
- `siteData` is a ref of an object that generated from user config, including [base](../../reference/config.md#base), [lang](../../reference/config.md#lang), [title](../../reference/config.md#title), [description](../../reference/config.md#description), [head](../../reference/config.md#head) and [locales](../../reference/config.md#locales).

The `enhance` function will be invoked after the client app is created. It's possible to implement any enhancements to the Vue application.

### Register Vue Components

You can register global Vue components via the [app.component](https://vuejs.org/api/application.html#app-component) method:

```ts
import { defineClientConfig } from '@vuepress/client'
import MyComponent from './MyComponent.vue'

export default defineClientConfig({
enhance({ app }) {
app.component('MyComponent', MyComponent)
},
})
```

### Use Non-SSR-Friendly Features

VuePress will generate a SSR application to pre-render pages during build. Generally speaking, if a code snippet is using Browser / DOM APIs before client app is mounted, we call it non-SSR-friendly.

We already provides a [ClientOnly](../../reference/components.md#clientonly) component to wrap non-SSR-friendly content.

In the `enhance` function, you can make use of the [`__VUEPRESS_SSR__`](../../reference/client-api.md#ssr) flag for that purpose.

```ts
import { defineClientConfig } from '@vuepress/client'

export default defineClientConfig({
async enhance() {
if (!__VUEPRESS_SSR__) {
const nonSsrFriendlyModule = await import('non-ssr-friendly-module')
// ...
}
},
})
```

### Use Router Methods

You can make use of the [Router Methods](https://router.vuejs.org/api/#router-methods) that provided by vue-router. For example, add navigation guard:

```ts
import { defineClientConfig } from '@vuepress/client'

export default defineClientConfig({
enhance({ router }) {
router.beforeEach((to) => {
console.log('before navigation')
})

router.afterEach((to) => {
console.log('after navigation')
})
},
})
```

::: warning
It's not recommended to use `addRoute` method to add dynamic routes here, because those routes will **NOT** be pre-rendered in build mode.

But you can still do that if you understand the drawback.
:::

## setup

The `setup` function would be invoked inside the [setup](https://vuejs.org/api/composition-api-setup.html) hook of the client vue app.

### Use Composition API

You can take the `setup` function as part of the [setup](https://vuejs.org/api/composition-api-setup.html) hook of the root component. Thus, all composition APIs are available here.

```ts
import { defineClientConfig } from '@vuepress/client'
import { provide, ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'

export default defineClientConfig({
setup() {
// get the current route location
const route = useRoute()
// get the vue-router instance
const router = useRouter()
// provide a value that can be injected by layouts, pages and other components
const count = ref(0)
provide('count', count)
}
})
```

### Use Non-SSR-Friendly Features

In the `setup` function, the [`__VUEPRESS_SSR__`](../../reference/client-api.md#ssr) flag is also available.

Another way to use non-ssr-friendly features is to put them inside the [onMounted](https://vuejs.org/api/composition-api-lifecycle.html#onmounted) hook:

```ts
import { defineClientConfig } from '@vuepress/client'
import { onMounted } from 'vue'

export default defineClientConfig({
setup() {
onMounted(() => {
// use DOM API after mounted
document.querySelector('#app')
})
}
})
```

## rootComponents

The `rootComponents` is a components array to be placed directly into the root node of the client vue app.

Typical usage of this option is to put some global UI components, like global popup or so:

```ts
import { defineClientConfig } from '@vuepress/client'
import GlobalPopup from './components/GlobalPopup.vue'

export default defineClientConfig({
rootComponents: [GlobalPopup],
})
```
51 changes: 49 additions & 2 deletions docs/guide/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Without any configuration, the VuePress site is pretty minimal. To customize you
└─ package.json
```

The essential file for configuring a VuePress site is `.vuepress/config.js`, while TypeScript config file is also supported. You can use `.vuepress/config.ts` instead to get better types hint for VuePress Config.
The essential file for configuring a VuePress site is `.vuepress/config.js`, while TypeScript config file is also supported. You can use `.vuepress/config.ts` instead to get better types hint for VuePress config.

To be more specific, we have a convention for config file paths (in order of precedence):

Expand All @@ -26,7 +26,11 @@ To be more specific, we have a convention for config file paths (in order of pre
- `.vuepress/config.js`
- `.vuepress/config.cjs`

You can also specify the config file via `--config` option of [CLI](./cli.md).
You can also specify the config file via `--config` option of [CLI](./cli.md):

```sh
vuepress dev docs --config my-config.js
```

A basic config file looks like this:

Expand Down Expand Up @@ -61,3 +65,46 @@ export default defineUserConfig({
::: tip
Check out the [Config Reference](../reference/config.md) for a full list of VuePress config.
:::

## Client Config File

In most cases, the config file is sufficient to configure your VuePress site. However, sometimes users may want to add some client-side code directly. To help with this, VuePress also supports a client config file:

```
├─ docs
│ ├─ .vuepress
│ │ ├─ client.js <--- client config file
│ │ └─ config.js <--- config file
│ └─ README.md
├─ .gitignore
└─ package.json
```

Similarly, we also have a convention for client config file paths (in order of precedence):

- In current working directory `cwd`:
- `vuepress.client.ts`
- `vuepress.client.js`
- `vuepress.client.mjs`
- In source directory `sourceDir`:
- `.vuepress/client.ts`
- `.vuepress/client.js`
- `.vuepress/client.mjs`

Notice that the client config file should be in ESM format:

```ts
import { defineClientConfig } from '@vuepress/client'

export default defineClientConfig({
enhance({ app, router, siteData }) {},
setup() {},
rootComponents: [],
})
```

::: tip
Unlike config file, client config file could not be specified via CLI options.

To learn more about client config file, see [Advanced > Cookbook > Usage of Client Config](../advanced/cookbook/usage-of-client-config.md)
:::
18 changes: 8 additions & 10 deletions docs/guide/migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,17 +220,15 @@ If you are using default theme, the palette system is still available but migrat

#### .vuepress/enhanceApp.js

Renamed to `.vuepress/clientAppEnhance.{js,ts}`.
Renamed to `.vuepress/client.{js,ts}`, and the usage has been changed, too.

The arguments of the function are changed, too.

See [Client API > defineClientAppEnhance](../reference/client-api.md#defineclientappenhance).
See [Advanced > Cookbook > Usage of Client Config](../advanced/cookbook/usage-of-client-config.md).

#### .vuepress/components/

Files in this directory will not be registered as Vue components automatically.

You need to use [@vuepress/plugin-register-components](../reference/plugin/register-components.md), or register your components manually in `.vuepress/clientAppEnhance.{js,ts}`.
You need to use [@vuepress/plugin-register-components](../reference/plugin/register-components.md), or register your components manually in `.vuepress/client.{js,ts}`.

#### .vuepress/theme/

Expand Down Expand Up @@ -302,9 +300,9 @@ For more detailed guide about how to write a plugin in v2, see [Advanced > Writi
- `generated`: renamed to `onGenerated`
- `additionalPages`: removed, use `app.pages.push(createPage())` in `onInitialized` hook
- `clientDynamicModules`: removed, use `app.writeTemp()` in `onPrepared` hook
- `enhanceAppFiles`: renamed to `clientAppEnhanceFiles`
- `globalUIComponents`: renamed to `clientAppRootComponentFiles`
- `clientRootMixin`: renamed to`clientAppSetupFiles`
- `enhanceAppFiles`: removed, use `clientConfigFile` hook
- `globalUIComponents`: removed, use `clientConfigFile` hook
- `clientRootMixin`: removed, use `clientConfigFile` hook
- `extendMarkdown`: renamed to `extendsMarkdown`
- `chainMarkdown`: removed
- `extendPageData`: renamed to `extendsPage`
Expand All @@ -323,8 +321,8 @@ Although we do not allow using other plugins in a plugin, you can still use plug
Some major breaking changes:

- There is no **conventional theme directory structure** anymore.
- The file `theme/enhanceApp.js` or `theme/clientAppEnhance.{js,ts}` will not be used as client app enhance file implicitly. You need to specify it explicitly in `clientAppEnhanceFiles` hook.
- Files in `theme/global-components/` directory will not be registered as Vue components automatically. You need to use [@vuepress/plugin-register-components](../reference/plugin/register-components.md), or register components manually in `clientAppEnhance.{js,ts}`.
- The file `theme/enhanceApp.js` will not be used as client app enhance file implicitly. You need to specify it explicitly in `clientConfigFile` hook.
- Files in `theme/global-components/` directory will not be registered as Vue components automatically. You need to use [@vuepress/plugin-register-components](../reference/plugin/register-components.md), or register components manually in `clientConfigFile`.
- Files in `theme/layouts/` directory will not be registered as layout components automatically. You need to specify it explicitly in `layouts` option.
- Files in `theme/templates/` directory will not be used as dev / ssr template automatically. You need to specify theme explicitly in `templateBuild` and `templateDev` option.
- Always provide a valid js entry file, and do not use `"main": "layouts/Layout.vue"` as the theme entry anymore.
Expand Down
Loading