refactor!: move vuepress-plugin-netlify-functions to another repo
This commit is contained in:
parent
10cb625401
commit
4132167597
@ -1,21 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (C) 2021 - PRESENT by pengzhanbo
|
||||
|
||||
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.
|
||||
@ -1,108 +0,0 @@
|
||||
# `vuepress-plugin-netlify-functions`
|
||||
|
||||
English | [简体中文](./README.md)
|
||||
|
||||
If your vuepress site is deployed on `netlify` and you want to be able to use `netlify functions` for `serverless`.
|
||||
|
||||
You may need this plugin to provide support.
|
||||
|
||||
## Features
|
||||
|
||||
- On the Vuepress local server, start a `Netlify Functions` local service to help you debug `functions` locally.
|
||||
- Generate a usable `netlify.toml` and add the appropriate 'functions' configurations if you have already created`netlify.toml`
|
||||
- This plugin does not provide specific `function` scripts, only `netlify functions` support;
|
||||
It can be used directly in themes, directly in vuepress projects, or based on this plugin,
|
||||
new plugins can be developed to provide more detailed functionality support.
|
||||
- Use `dotenv` to provide support similar to `Netlify Environment variables` in the local service
|
||||
environment. Create `.env` files in the project root directory to hold development-time environment variables
|
||||
|
||||
## Install
|
||||
|
||||
```sh
|
||||
npm install vuepress-plugin-netlify-functions
|
||||
# or
|
||||
pnpm add vuepress-plugin-netlify-functions
|
||||
# or
|
||||
yarn add vuepress-plugin-netlify-functions
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
1. In a Vuepress project, or in a Vuepress theme
|
||||
|
||||
``` js
|
||||
// .vuepress/config.[jt]s
|
||||
import { netlifyFunctionsPlugin } from 'vuepress-plugin-netlify-functions'
|
||||
|
||||
export default {
|
||||
// ...
|
||||
plugins: [
|
||||
netlifyFunctionsPlugin()
|
||||
]
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
2. In a vuepress plugin:
|
||||
|
||||
``` ts
|
||||
import { useNetlifyFunctionsPlugin } from 'vuepress-plugin-netlify-functions'
|
||||
|
||||
function myPlugin(): Plugin {
|
||||
return (app: App) => {
|
||||
const {
|
||||
// proxy prefix, default: /api
|
||||
proxyPrefix,
|
||||
preparePluginFunctions,
|
||||
generatePluginFunctions
|
||||
} = useNetlifyFunctionsPlugin(app, {
|
||||
// Specifies the functions directory for the plugin where the relevant scripts are developed
|
||||
directory: path.resolve(__dirname, 'functions')
|
||||
})
|
||||
return {
|
||||
name: 'vuepress-plugin-myPlugin',
|
||||
onPrepared: () => preparePluginFunctions(),
|
||||
onGenerated: () => generatePluginFunctions(),
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Methods
|
||||
|
||||
### `netlifyFunctionsPlugin(options)`
|
||||
|
||||
plugin function
|
||||
|
||||
In the Vuepress configuration, or in the Vuepress topic configuration.
|
||||
|
||||
#### options
|
||||
|
||||
- `options.sourceDirectory` functions source directory。
|
||||
|
||||
@default `app.dir.source('.vuepress/functions')。
|
||||
|
||||
- `options.destDirectory` functions output directory
|
||||
|
||||
@default `app.dir.dest('function')
|
||||
|
||||
- `options.proxyPrefix` server proxy prefix
|
||||
|
||||
@default `/api`。
|
||||
|
||||
functions request to proxy `^/api/*`
|
||||
|
||||
### `useNetlifyFunctionsPlugin(app, options)`
|
||||
|
||||
Used in the plugin when developing the VuePress plugin
|
||||
|
||||
- `app`: **App**
|
||||
|
||||
- `options.directory`
|
||||
|
||||
Functions development directory in plugin
|
||||
|
||||
## Example
|
||||
|
||||
- [vuepress-plugin-page-collection](https://github.com/pengzhanbo/vuepress-theme-plume/tree/main/packages/plugin-page-collection)
|
||||
Log and display the number of page views/visits of blog articles by connecting `leanCloud` in functions based on `netlify-functions`
|
||||
@ -1,113 +0,0 @@
|
||||
# `vuepress-plugin-netlify-functions`
|
||||
|
||||
[English](./README.en-US.md) | 简体中文
|
||||
|
||||
如果你的 vuepress 站点是部署在 `netlify` 的,而且希望能够使用`netlify functions` 来做 `serverless`。
|
||||
|
||||
那么你可能需要本插件提供支持。
|
||||
|
||||
## 功能
|
||||
|
||||
- 在 vuepress 本地服务器上,启动一个 `netlify functions` 本地服务,帮助你在本地对 `functions` 进行调试。
|
||||
- 帮助生成一个 可用的 `netlify.toml` ,如果你已经创建了 `netlify.toml`,会添加合适的 `functions` 配置
|
||||
- 本插件不提供具体的 `function` 脚本,仅提供 `netlify functions` 支持;可以在主题中直接只用,也可以在 vuepress 项目中直接使用,也可以基于本插件,开发新的插件提供更详细的功能支持。
|
||||
- 使用 `dotenv` 在本地服务环境提供 类似于 `netlify environment variables` 支持。 在项目根目录下 创建 `.env` 文件用于保存开发时环境变量
|
||||
|
||||
## 安装
|
||||
|
||||
```sh
|
||||
npm install vuepress-plugin-netlify-functions
|
||||
# or
|
||||
pnpm add vuepress-plugin-netlify-functions
|
||||
# or
|
||||
yarn add vuepress-plugin-netlify-functions
|
||||
```
|
||||
|
||||
## 使用
|
||||
|
||||
1. 在 vuepress 项目中,或者在一个 vuepress 主题中
|
||||
|
||||
``` js
|
||||
// .vuepress/config.[jt]s
|
||||
import { netlifyFunctionsPlugin } from 'vuepress-plugin-netlify-functions'
|
||||
|
||||
export default {
|
||||
// ...
|
||||
plugins: [
|
||||
netlifyFunctionsPlugin()
|
||||
]
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
2. 在 vuepress plugin 中:
|
||||
|
||||
``` ts
|
||||
import { useNetlifyFunctionsPlugin } from 'vuepress-plugin-netlify-functions'
|
||||
|
||||
function myPlugin(): Plugin {
|
||||
return (app: App) => {
|
||||
const {
|
||||
// 请求前缀, 默认 /api
|
||||
proxyPrefix,
|
||||
preparePluginFunctions,
|
||||
generatePluginFunctions
|
||||
} = useNetlifyFunctionsPlugin(app, {
|
||||
// 指定插件的functions目录,相关脚本在此目录中开发
|
||||
directory: path.resolve(__dirname, 'functions')
|
||||
})
|
||||
return {
|
||||
name: 'vuepress-plugin-myPlugin',
|
||||
onPrepared: () => preparePluginFunctions(),
|
||||
onGenerated: () => generatePluginFunctions(),
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Methods
|
||||
|
||||
### `netlifyFunctionsPlugin(options)`
|
||||
|
||||
插件函数。
|
||||
|
||||
在 vuepress 配置中,或者在 vuepress 主题配置中使用。
|
||||
|
||||
#### options
|
||||
|
||||
- `options.sourceDirectory` functions 源文件夹。
|
||||
|
||||
默认 `app.dir.source('.vuepress/functions') 目录。
|
||||
|
||||
- `options.destDirectory` functions 输出文件夹。
|
||||
|
||||
默认 `app.dir.dest('function') 目录
|
||||
|
||||
- `options.proxyPrefix` proxy代理前缀。
|
||||
|
||||
默认 `/api`。
|
||||
|
||||
functions下的请求通过 `/api` 转发
|
||||
|
||||
### `useNetlifyFunctionsPlugin(app, options)`
|
||||
|
||||
在 开发 vuepress 插件时, 在插件中使用
|
||||
|
||||
- `app`: **App**
|
||||
|
||||
- `options.directory`
|
||||
|
||||
插件中的 functions 开发目录
|
||||
|
||||
## 查看详细说明文档
|
||||
|
||||
待补充
|
||||
|
||||
## Example
|
||||
|
||||
## 示例
|
||||
|
||||
### 插件开发示例
|
||||
|
||||
- [vuepress-plugin-page-collection](https://github.com/pengzhanbo/vuepress-theme-plume/tree/main/packages/plugin-page-collection)
|
||||
基于 netlify-functions 的,通过在 functions中连接 `leancloud` 实现 博客文章页 阅读数/访问次数 的记录与展示。
|
||||
@ -1,61 +0,0 @@
|
||||
{
|
||||
"name": "vuepress-plugin-netlify-functions",
|
||||
"type": "module",
|
||||
"version": "1.0.0-rc.71",
|
||||
"description": "The Plugin for VuePress 2, Support Netlify Functions",
|
||||
"author": "pengzhanbo <volodymyr@foxmail.com>",
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/pengzhanbo/vuepress-theme-plume#readme",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/pengzhanbo/vuepress-theme-plume.git",
|
||||
"directory": "plugins/plugin-netlify-functions"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/pengzhanbo/vuepress-theme-plume/issues"
|
||||
},
|
||||
"keywords": [
|
||||
"VuePress",
|
||||
"vuepress plugin",
|
||||
"netlify",
|
||||
"netlify functions",
|
||||
"netlifyFunctions",
|
||||
"vuepress-plugin-netlify-functions"
|
||||
],
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./lib/node/index.d.ts",
|
||||
"import": "./lib/node/index.js"
|
||||
},
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"main": "lib/node/index.js",
|
||||
"types": "lib/node/index.d.ts",
|
||||
"files": [
|
||||
"lib"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "pnpm run copy && pnpm run ts",
|
||||
"clean": "rimraf --glob ./lib ./*.tsbuildinfo",
|
||||
"copy": "cpx \"src/**/*.{d.ts,vue,css,scss,jpg,png}\" lib",
|
||||
"ts": "tsc -b tsconfig.build.json"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vuepress": "2.0.0-rc.14"
|
||||
},
|
||||
"dependencies": {
|
||||
"@iarna/toml": "^2.2.5",
|
||||
"@netlify/functions": "^2.8.0",
|
||||
"chalk": "^5.3.0",
|
||||
"chokidar": "^3.6.0",
|
||||
"cpx2": "^7.0.1",
|
||||
"dotenv": "^16.4.5",
|
||||
"esbuild": "^0.21.5",
|
||||
"execa": "^9.3.0",
|
||||
"netlify-cli": "^17.30.0",
|
||||
"portfinder": "^1.0.32"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
}
|
||||
@ -1,39 +0,0 @@
|
||||
import type { App } from 'vuepress/core'
|
||||
import type { NetlifyFunctionsPluginOptions } from '../shared/index.js'
|
||||
|
||||
export function extendsBundlerOptions(bundlerOption: any, app: App, options: NetlifyFunctionsPluginOptions, server: string): void {
|
||||
// 在 netlify-cli 的 function:serve 中,
|
||||
// 默认就是 指向 /.netlify/functions
|
||||
// 而配置的 --functions 仅作为源文件入口
|
||||
const targetPath = '/.netlify/functions'
|
||||
if (app.options.bundler.name === '@vuepress/bundler-vite') {
|
||||
const rewriteRE = new RegExp(`^${options.proxyPrefix}`)
|
||||
bundlerOption.viteOptions.server = bundlerOption.viteOptions.server || {}
|
||||
const viteServer = bundlerOption.viteOptions.server
|
||||
// 将 netlify functions server 代理到 当前的 vuepress 开发 服务器上
|
||||
viteServer.proxy = Object.assign(viteServer.proxy || {}, {
|
||||
[options.proxyPrefix as string]: {
|
||||
target: server,
|
||||
changeOrigin: true,
|
||||
rewrite: (url: string) => url.replace(rewriteRE, targetPath),
|
||||
},
|
||||
})
|
||||
}
|
||||
if (app.options.bundler.name === '@vuepress/bundler-webpack') {
|
||||
const rewritePath = `^${options.proxyPrefix}`
|
||||
bundlerOption.configureWebpack(
|
||||
(config: any, isServer: boolean, isBuild: boolean) => {
|
||||
if (isBuild)
|
||||
return
|
||||
config.devServer = config.devServer || {}
|
||||
config.devServer.proxy = Object.assign(config.devServer.proxy || {}, {
|
||||
[options.proxyPrefix as string]: {
|
||||
target: server,
|
||||
changeOrigin: true,
|
||||
pathRewrite: { [rewritePath]: targetPath },
|
||||
},
|
||||
})
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -1,10 +0,0 @@
|
||||
import type { NetlifyFunctionsOptions } from '../shared/index.js'
|
||||
import { netlifyFunctionsPlugin } from './plugin.js'
|
||||
|
||||
export * from './useNetlifyFunctionsPlugins.js'
|
||||
|
||||
export { type NetlifyFunctionsOptions }
|
||||
|
||||
export { netlifyFunctionsPlugin }
|
||||
|
||||
export default netlifyFunctionsPlugin
|
||||
@ -1,3 +0,0 @@
|
||||
export * from './initFunctions.js'
|
||||
export * from './netlifyConfig.js'
|
||||
export * from './netlifyServer.js'
|
||||
@ -1,72 +0,0 @@
|
||||
import type { App } from 'vuepress/core'
|
||||
import { path } from 'vuepress/utils'
|
||||
import * as chokidar from 'chokidar'
|
||||
import esbuild from 'esbuild'
|
||||
import type { NetlifyFunctionsPluginOptions } from '../../shared/index.js'
|
||||
import { readFileList } from '../utils/index.js'
|
||||
|
||||
export async function generateFunctions(app: App, options: NetlifyFunctionsPluginOptions): Promise<void> {
|
||||
const { directory } = options
|
||||
const { source, dest } = directory
|
||||
const userSource = source[0]
|
||||
const files = readFileList(userSource)
|
||||
|
||||
if (files.length > 0) {
|
||||
await esbuild.build({
|
||||
entryPoints: files,
|
||||
outbase: userSource,
|
||||
outdir: dest,
|
||||
platform: 'node',
|
||||
format: 'cjs',
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export async function initialFunctions(app: App, options: NetlifyFunctionsPluginOptions): Promise<void> {
|
||||
if (!app.env.isDev)
|
||||
return
|
||||
const { directory } = options
|
||||
const { source, temp } = directory
|
||||
const userSource = source[0]
|
||||
const files = readFileList(userSource)
|
||||
|
||||
if (files.length > 0) {
|
||||
await esbuild.build({
|
||||
entryPoints: files,
|
||||
outbase: userSource,
|
||||
outdir: temp,
|
||||
platform: 'node',
|
||||
format: 'cjs',
|
||||
})
|
||||
}
|
||||
watchFunctions(app, options)
|
||||
}
|
||||
|
||||
export function watchFunctions(app: App, { directory }: NetlifyFunctionsPluginOptions): void {
|
||||
const { source, temp } = directory
|
||||
const userSource = source[0]
|
||||
const watcher = chokidar.watch('**/*.ts', {
|
||||
cwd: userSource,
|
||||
ignoreInitial: true,
|
||||
})
|
||||
|
||||
watcher.on('add', async (file: string) => {
|
||||
await esbuild.build({
|
||||
entryPoints: [path.join(userSource, file)],
|
||||
outbase: userSource,
|
||||
outdir: temp,
|
||||
platform: 'node',
|
||||
format: 'cjs',
|
||||
})
|
||||
})
|
||||
|
||||
watcher.on('change', async (file: string) => {
|
||||
await esbuild.build({
|
||||
entryPoints: [path.join(userSource, file)],
|
||||
outbase: userSource,
|
||||
outdir: temp,
|
||||
platform: 'node',
|
||||
format: 'cjs',
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -1,62 +0,0 @@
|
||||
import process from 'node:process'
|
||||
import type { JsonMap } from '@iarna/toml'
|
||||
import { parse, stringify } from '@iarna/toml'
|
||||
import type { App } from 'vuepress/core'
|
||||
import { fs, path } from 'vuepress/utils'
|
||||
import type { NetlifyFunctionsPluginOptions } from '../../shared/index.js'
|
||||
|
||||
export interface NetlifyConfig {
|
||||
functions: Record<string, any>
|
||||
redirects: Record<string, any>[]
|
||||
}
|
||||
|
||||
const configName = 'netlify.toml'
|
||||
|
||||
function readConfig(filepath: string): NetlifyConfig {
|
||||
let netlifyConfig = ''
|
||||
if (fs.existsSync(filepath))
|
||||
netlifyConfig = fs.readFileSync(filepath, 'utf-8') || ''
|
||||
|
||||
return (parse(netlifyConfig) as unknown as NetlifyConfig) || {}
|
||||
}
|
||||
|
||||
function writeConfig(filepath: string, netlifyConfig: NetlifyConfig): void {
|
||||
fs.writeFileSync(
|
||||
filepath,
|
||||
stringify(netlifyConfig as unknown as JsonMap),
|
||||
'utf-8',
|
||||
)
|
||||
}
|
||||
|
||||
function resolveFunctions(config: NetlifyConfig, { directory }: NetlifyFunctionsPluginOptions, app: App): void {
|
||||
const functions = (config.functions = config.functions || {})
|
||||
functions.directory
|
||||
= functions.directory || path.relative(app.dir.dest('../'), directory.dest)
|
||||
}
|
||||
|
||||
function resolveRedirects(config: NetlifyConfig, { proxyPrefix }: NetlifyFunctionsPluginOptions): void {
|
||||
const funcDir = `/${(config.functions.directory || '').replace(/^\//, '')}`
|
||||
const redirects = (config.redirects = config.redirects || [])
|
||||
if (!redirects.some(redirect => redirect?.to?.startsWith(funcDir))) {
|
||||
redirects.push({
|
||||
from: path.join('/', proxyPrefix, '*'),
|
||||
to: path.join(funcDir, ':splat'),
|
||||
status: 200,
|
||||
force: true,
|
||||
Headers: {
|
||||
'X-From': 'Netlify',
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export function generateNetlifyConfig(app: App, options: NetlifyFunctionsPluginOptions): NetlifyConfig {
|
||||
const configPath = path.join(process.cwd(), configName)
|
||||
const config = readConfig(configPath)
|
||||
|
||||
resolveFunctions(config, options, app)
|
||||
resolveRedirects(config, options)
|
||||
|
||||
writeConfig(configPath, config)
|
||||
return config
|
||||
}
|
||||
@ -1,59 +0,0 @@
|
||||
import { Buffer } from 'node:buffer'
|
||||
import process from 'node:process'
|
||||
import { fs, getDirname, path } from 'vuepress/utils'
|
||||
import dotenv from 'dotenv'
|
||||
import { execa } from 'execa'
|
||||
import * as portFinder from 'portfinder'
|
||||
import type { NetlifyFunctionsPluginOptions } from '../../shared/index.js'
|
||||
|
||||
const __dirname = getDirname(import.meta.url)
|
||||
|
||||
function loadEnvConfig(): Record<string, string | undefined> {
|
||||
const configPath = path.resolve(process.cwd(), '.env')
|
||||
if (!fs.existsSync(configPath))
|
||||
return {}
|
||||
|
||||
try {
|
||||
const content = fs.readFileSync(configPath, 'utf-8')
|
||||
return dotenv.parse(Buffer.from(content))
|
||||
}
|
||||
catch {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
|
||||
export interface NetlifyServe {
|
||||
host: string
|
||||
close: () => void
|
||||
}
|
||||
export async function netlifyServe({
|
||||
directory,
|
||||
}: NetlifyFunctionsPluginOptions): Promise<NetlifyServe> {
|
||||
const port = await portFinder.getPortPromise({ port: 9000 })
|
||||
|
||||
const argv = [
|
||||
'functions:serve',
|
||||
'--port',
|
||||
`${port}`,
|
||||
'--functions',
|
||||
path.join('./', path.relative(process.cwd(), directory.temp)),
|
||||
// '--debug',
|
||||
]
|
||||
|
||||
const { stdout, kill } = execa(
|
||||
path.resolve(__dirname, '../../../node_modules/.bin/netlify'),
|
||||
argv,
|
||||
{
|
||||
cwd: process.cwd(),
|
||||
env: {
|
||||
...loadEnvConfig(),
|
||||
},
|
||||
},
|
||||
)
|
||||
stdout?.pipe(process.stdout)
|
||||
|
||||
return {
|
||||
host: `http://localhost:${port}`,
|
||||
close: () => kill(),
|
||||
}
|
||||
}
|
||||
@ -1,103 +0,0 @@
|
||||
/**
|
||||
* 如果是把 vuepress 站点部署的 netlify上,那么可以借助 netlify 上的 functions 功能,
|
||||
* 为我们的站点提供 serverless 能力。
|
||||
*
|
||||
* 比如,通过这个插件,在functions 中 连接 类似 firebase 等 数据存储服务,
|
||||
* 可以用来存储一些如 页面访问次数、访客总数等。还可以基于此来开发如 博客 留言墙、说说 等功能
|
||||
*
|
||||
* 为了使这个插件能够更加通用,同时可以成为其他插件的依赖
|
||||
* 在设计上,本插件仅作为 netlify functions server,
|
||||
* 并将提代理到 vuepress 的开发服务器上。
|
||||
* 同时收集 用户自定义的 functions 脚本,以及其他插件提供的 functions 脚本
|
||||
*
|
||||
* 在开发环境中,所有脚本 默认都被 编译到 .vuepress/.temp/functions 目录中。
|
||||
* netlify 本地 functions server 也将指向这个目录。
|
||||
* 启动的服务器, 请求functions的地址为:
|
||||
* http://localhost:{port}/.netlify/functions/{function-name}
|
||||
*
|
||||
* 出于通用性考虑,本插件应该优先于 依赖本插件的其他插件 之前进行加载。
|
||||
*
|
||||
* 在其他插件中应该使用 useNetlifyFunctionsPlugin() 来获取 本插件的功能
|
||||
*
|
||||
* 待解决的问题:
|
||||
* - 其他插件如果使用了非 用户定义的 proxyPrefix, 是否要在 netlify.toml 中
|
||||
* 再生成一个 redirect 配置
|
||||
* - 如何解决可能存在的 插件之间的 functions 命名冲突
|
||||
*
|
||||
*/
|
||||
import type { App, Plugin } from 'vuepress/core'
|
||||
import type {
|
||||
NetlifyFunctionsOptions,
|
||||
NetlifyFunctionsPluginOptions,
|
||||
} from '../shared/index.js'
|
||||
import { extendsBundlerOptions } from './extendsBundlerOptions.js'
|
||||
import type { NetlifyServe } from './netlify/index.js'
|
||||
import {
|
||||
generateFunctions,
|
||||
generateNetlifyConfig,
|
||||
initialFunctions,
|
||||
netlifyServe,
|
||||
} from './netlify/index.js'
|
||||
|
||||
function initOptions(app: App, {
|
||||
sourceDirectory,
|
||||
destDirectory,
|
||||
proxyPrefix = '/api',
|
||||
}: NetlifyFunctionsOptions): NetlifyFunctionsPluginOptions {
|
||||
return {
|
||||
directory: {
|
||||
source: [sourceDirectory || app.dir.source('.vuepress/functions')],
|
||||
dest: destDirectory || app.dir.dest('functions'),
|
||||
temp: app.dir.temp('functions'),
|
||||
},
|
||||
proxyPrefix,
|
||||
}
|
||||
}
|
||||
|
||||
const cache = {
|
||||
options: {},
|
||||
}
|
||||
|
||||
export function getOptions(): NetlifyFunctionsPluginOptions {
|
||||
return cache.options as NetlifyFunctionsPluginOptions
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* netlify function 插件,提供 netlify functions 支持
|
||||
*
|
||||
* @param options
|
||||
*/
|
||||
export function netlifyFunctionsPlugin(options: NetlifyFunctionsOptions = {}): Plugin {
|
||||
return (app: App) => {
|
||||
const opts = initOptions(app, options)
|
||||
let server: NetlifyServe
|
||||
cache.options = opts
|
||||
return {
|
||||
name: 'vuepress-plugin-netlify-functions',
|
||||
|
||||
onInitialized: async (app) => {
|
||||
// 启动netlify functions server
|
||||
if (!app.env.isBuild) {
|
||||
// 初始化用户侧的 functions
|
||||
await initialFunctions(app, opts)
|
||||
server = await netlifyServe(opts)
|
||||
}
|
||||
},
|
||||
|
||||
onWatched: (app, watchers) => {
|
||||
watchers.push(server)
|
||||
},
|
||||
|
||||
extendsBundlerOptions: (bundlerOption, app: App) => {
|
||||
extendsBundlerOptions(bundlerOption, app, opts, server.host)
|
||||
},
|
||||
|
||||
onGenerated: async (app: App) => {
|
||||
// 生成配置文件
|
||||
generateNetlifyConfig(app, opts)
|
||||
await generateFunctions(app, opts)
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,5 +0,0 @@
|
||||
declare module 'cpx2' {
|
||||
const watch: any
|
||||
const copy: any
|
||||
export { watch, copy }
|
||||
}
|
||||
@ -1,57 +0,0 @@
|
||||
import type { App, PluginObject } from 'vuepress/core'
|
||||
import { path } from 'vuepress/utils'
|
||||
import * as cpx2 from 'cpx2'
|
||||
import type { UseNetlifyFunctionPluginsOptions } from '../shared/index.js'
|
||||
import { getOptions, netlifyFunctionsPlugin } from './plugin.js'
|
||||
|
||||
interface UseNetlifyFunctionResult {
|
||||
/**
|
||||
* functions 请求前缀
|
||||
*/
|
||||
proxyPrefix: string
|
||||
|
||||
/**
|
||||
* 在 插件的 onPrepare 钩子中调用,监听 当前插件的 functions 目录
|
||||
*/
|
||||
preparePluginFunctions: () => void
|
||||
/**
|
||||
* 在 插件的 onGenerate 钩子中调用,将 当前插件的 functions 文件推送到 dest中
|
||||
*/
|
||||
generatePluginFunctions: () => void
|
||||
}
|
||||
export function useNetlifyFunctionsPlugin(app: App, options: UseNetlifyFunctionPluginsOptions): UseNetlifyFunctionResult {
|
||||
if (typeof options === 'undefined')
|
||||
throw new Error('useNetlifyFunctionsPlugin [options] argument not found.')
|
||||
|
||||
if (typeof options.directory !== 'string' || !options.directory) {
|
||||
throw new Error(
|
||||
`useNetlifyFunctionsPlugin [options.directory] must be a string\n exp: path.join(__dirname, 'functions')`,
|
||||
)
|
||||
}
|
||||
const plugins = app.pluginApi.plugins
|
||||
if (
|
||||
!plugins.some(
|
||||
(plugin: PluginObject) =>
|
||||
plugin.name === 'vuepress-plugin-netlify-functions',
|
||||
)
|
||||
) {
|
||||
app.use(netlifyFunctionsPlugin())
|
||||
}
|
||||
|
||||
const { proxyPrefix, directory } = getOptions()
|
||||
const source = path.join(options.directory, '**/*.js')
|
||||
|
||||
function preparePluginFunctions(): void {
|
||||
if (!app.env.isBuild) {
|
||||
cpx2.watch(source, directory.temp, {
|
||||
ignore: ['!**/*.d.js'],
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function generatePluginFunctions(): void {
|
||||
cpx2.copy(source, directory.dest)
|
||||
}
|
||||
|
||||
return { proxyPrefix, preparePluginFunctions, generatePluginFunctions }
|
||||
}
|
||||
@ -1 +0,0 @@
|
||||
export * from './readFileList.js'
|
||||
@ -1,19 +0,0 @@
|
||||
import { fs, path } from 'vuepress/utils'
|
||||
|
||||
export function readFileList(source: string, fileList: string[] = []): string[] {
|
||||
if (!fs.existsSync(source))
|
||||
return []
|
||||
const files = fs.readdirSync(source)
|
||||
files.forEach((file: string) => {
|
||||
const filepath = path.join(source, file)
|
||||
const stat = fs.statSync(filepath)
|
||||
if (stat.isDirectory()) {
|
||||
if (file !== 'node_modules')
|
||||
readFileList(filepath, fileList)
|
||||
}
|
||||
else {
|
||||
fileList.push(filepath)
|
||||
}
|
||||
})
|
||||
return fileList
|
||||
}
|
||||
@ -1,39 +0,0 @@
|
||||
export interface NetlifyFunctionsOptions {
|
||||
/**
|
||||
* netlify functions source directory
|
||||
*
|
||||
* netlify functions 源码目录
|
||||
*
|
||||
* @default `app.dir.source('.vuepress/functions')`
|
||||
*/
|
||||
sourceDirectory?: string
|
||||
|
||||
/**
|
||||
* netlify functions output directory
|
||||
*
|
||||
* netlify functions 输出目录
|
||||
*
|
||||
* @default `app.dir.dest('functions')`
|
||||
*/
|
||||
destDirectory?: string
|
||||
|
||||
/**
|
||||
* 请求代理来源,将会转发到 functions directory
|
||||
*
|
||||
* @default `/api`
|
||||
*/
|
||||
proxyPrefix?: string
|
||||
}
|
||||
|
||||
export interface NetlifyFunctionsPluginOptions {
|
||||
directory: {
|
||||
dest: string
|
||||
source: string[]
|
||||
temp: string
|
||||
}
|
||||
proxyPrefix: string
|
||||
}
|
||||
|
||||
export interface UseNetlifyFunctionPluginsOptions {
|
||||
directory: string
|
||||
}
|
||||
@ -1,8 +0,0 @@
|
||||
{
|
||||
"extends": "../tsconfig.build.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./lib"
|
||||
},
|
||||
"include": ["./src"]
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (C) 2021 - PRESENT by pengzhanbo
|
||||
|
||||
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.
|
||||
@ -1,77 +0,0 @@
|
||||
# `@vuepress-plume/plugin-page-collection`
|
||||
|
||||
这是一个使用了 `netlify functions` + `leancloud` 的 `VuePress2` 插件示例。
|
||||
|
||||
- 功能: 进入页面时,记录访问次数,并提供一个 组件展示页面访问次数。
|
||||
|
||||
## Why ?
|
||||
|
||||
- 为什么是在 `netlify functions` 中 连接 `leancloud` ,而不是直接在 web客户端中请求 `leancloud` ?
|
||||
|
||||
这是出于数据安全的角度考虑,避免直接在浏览器可见的代码中暴露私密的鉴权信息。
|
||||
|
||||
## 使用方式
|
||||
|
||||
> (仅示例,本插件未发布到 npm)
|
||||
|
||||
- 在 vuepress 配置插件
|
||||
|
||||
``` ts
|
||||
export default defineUserConfig({
|
||||
plugins: [
|
||||
pageCollectionPlugin()
|
||||
]
|
||||
})
|
||||
```
|
||||
|
||||
- 在需要做页面记录的路由级组件中引入`<PageCollection>`组件
|
||||
|
||||
``` html
|
||||
<Page>
|
||||
<PageCollection />
|
||||
</Page>
|
||||
```
|
||||
|
||||
- 在项目根目录 新建 `.env` 文件
|
||||
> 开发时使用,发布到生产时,需要在 netlify 中配置 环境变量。
|
||||
> 同时,需要将 `.env` 文件添加到 `.ignore`中,避免暴露
|
||||
|
||||
```sh
|
||||
LEAN_CLOUD_APP_ID='your leancloud appId'
|
||||
LEAN_CLOUD_APP_KEY='your leancloud appKey'
|
||||
LEAN_CLOUD_MASTER_KEY='your leancloud masterKey'
|
||||
```
|
||||
|
||||
效果:
|
||||
|
||||
``` html
|
||||
阅读数:99
|
||||
```
|
||||
|
||||
## 结构
|
||||
|
||||
``` SH
|
||||
.
|
||||
├── database # leancloud-storage
|
||||
│ └── Page.json # Object Page 在 leancloud控制台中导入即可使用
|
||||
├── src # 源码
|
||||
│ ├── client
|
||||
│ │ ├── clientAppEnhance.ts # 注入全局组件
|
||||
│ │ ├── components
|
||||
| | | └── PageCollection.ts # 组件
|
||||
│ │ └── composables
|
||||
| | ├── index.ts
|
||||
| | └── usePageCollection.ts # 请求 functions
|
||||
│ ├── node
|
||||
│ │ ├── functions # netlify functions 文件夹
|
||||
| | | └── page_collection.ts # 连接 leancloud 获取 page数据
|
||||
│ │ ├── index.ts
|
||||
│ │ └── plugin.ts # 插件配置
|
||||
│ └── shared
|
||||
│ └── index.ts
|
||||
└── package.json
|
||||
```
|
||||
|
||||
## 主要代码说明
|
||||
|
||||
请查看源码注释
|
||||
@ -1,46 +0,0 @@
|
||||
{
|
||||
"schema": {
|
||||
"updatedAt": { "type": "Date" },
|
||||
"ACL": {
|
||||
"type": "ACL",
|
||||
"default": { "_owner": { "write": true }, "*": { "read": true } },
|
||||
"hidden": true
|
||||
},
|
||||
"objectId": { "type": "String" },
|
||||
"createdAt": { "type": "Date" },
|
||||
"url": {
|
||||
"type": "String",
|
||||
"v": 2,
|
||||
"required": false,
|
||||
"comment": "页面路径",
|
||||
"hidden": false,
|
||||
"read_only": false
|
||||
},
|
||||
"visitCount": {
|
||||
"type": "Number",
|
||||
"v": 2,
|
||||
"required": false,
|
||||
"auto_increment": false,
|
||||
"default": 0,
|
||||
"comment": "访问次数",
|
||||
"hidden": false,
|
||||
"read_only": false
|
||||
}
|
||||
},
|
||||
"permissions": {
|
||||
"create": { "*": true },
|
||||
"find": { "onlySignInUsers": true },
|
||||
"get": { "onlySignInUsers": true },
|
||||
"update": { "onlySignInUsers": true },
|
||||
"delete": { "onlySignInUsers": true },
|
||||
"add_fields": { "onlySignInUsers": true }
|
||||
},
|
||||
"indexes": [
|
||||
{
|
||||
"v": 2,
|
||||
"key": { "url": 1 },
|
||||
"name": "-user-url_1",
|
||||
"background": true
|
||||
}
|
||||
]
|
||||
}
|
||||
@ -1,52 +0,0 @@
|
||||
{
|
||||
"name": "plugin-page-collection",
|
||||
"type": "module",
|
||||
"version": "1.0.0-rc.71",
|
||||
"private": true,
|
||||
"description": "The Plugin for VuePress 2",
|
||||
"author": "pengzhanbo <volodymyr@foxmail.com>",
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/pengzhanbo/vuepress-theme-plume#readme",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/pengzhanbo/vuepress-theme-plume.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/pengzhanbo/vuepress-theme-plume/issues"
|
||||
},
|
||||
"exports": {
|
||||
".": "./lib/node/index.js",
|
||||
"./client": "./lib/client/index.js",
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"main": "lib/node/index.js",
|
||||
"types": "lib/node/index.d.ts",
|
||||
"files": [
|
||||
"lib"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "pnpm run copy && pnpm run ts",
|
||||
"clean": "rimraf --glob ./lib ./*.tsbuildinfo",
|
||||
"copy": "cpx \"src/**/*.{d.ts,vue,css,scss,jpg,png}\" lib",
|
||||
"ts": "tsc -b tsconfig.build.json"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vuepress": "2.0.0-rc.14"
|
||||
},
|
||||
"dependencies": {
|
||||
"@netlify/functions": "^2.8.0",
|
||||
"leancloud-storage": "^4.15.2",
|
||||
"vue": "^3.4.30",
|
||||
"vue-router": "4.3.2",
|
||||
"vuepress-plugin-netlify-functions": "workspace:~"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"keyword": [
|
||||
"VuePress",
|
||||
"vuepress plugin",
|
||||
"page collection",
|
||||
"vuepress-plugin-page-collection"
|
||||
]
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
import { defineClientConfig } from 'vuepress/client'
|
||||
import type { ClientConfig } from 'vuepress/client'
|
||||
import Collection from './components/PageCollection.js'
|
||||
|
||||
export default defineClientConfig({
|
||||
enhance({ app }) {
|
||||
app.component('PageCollection', Collection)
|
||||
},
|
||||
}) as ClientConfig
|
||||
@ -1,17 +0,0 @@
|
||||
import { defineComponent, h } from 'vue'
|
||||
import { usePageCollection } from '../composables/index.js'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'PageCollection',
|
||||
setup() {
|
||||
const collection = usePageCollection()
|
||||
return () =>
|
||||
h(
|
||||
'span',
|
||||
{
|
||||
class: 'page-collection',
|
||||
},
|
||||
`阅读数:${collection.visitCount}`,
|
||||
)
|
||||
},
|
||||
})
|
||||
@ -1 +0,0 @@
|
||||
export * from './usePageCollection.js'
|
||||
@ -1,51 +0,0 @@
|
||||
import { onMounted, reactive } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
|
||||
declare const __COLLECTION_PROXY_PREFIX__: string
|
||||
|
||||
const prefix = __COLLECTION_PROXY_PREFIX__
|
||||
|
||||
interface PageCollection {
|
||||
visitCount: number
|
||||
}
|
||||
|
||||
interface ResponseData {
|
||||
code: number
|
||||
result: Record<string, any>
|
||||
}
|
||||
|
||||
async function fetchCollection(url: string): Promise<PageCollection> {
|
||||
// 发起 netlify functions 请求
|
||||
// 你已经注意到,接口名就是在 node/functions 目录下的 文件名
|
||||
const response = await fetch(`${prefix}/page_collection`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ url }),
|
||||
})
|
||||
const result = (await response.json()) as unknown as ResponseData
|
||||
if (result.code === 200) {
|
||||
return (result.result || {}) as PageCollection
|
||||
}
|
||||
else {
|
||||
return {
|
||||
visitCount: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function usePageCollection(): PageCollection {
|
||||
const collection = reactive({
|
||||
visitCount: 0,
|
||||
})
|
||||
const route = useRoute()
|
||||
const getPageCollection = async (url: string): Promise<void> => {
|
||||
const { visitCount } = await fetchCollection(url)
|
||||
collection.visitCount = visitCount
|
||||
}
|
||||
onMounted(() => {
|
||||
setTimeout(async () => {
|
||||
await getPageCollection(route.path)
|
||||
}, 0)
|
||||
})
|
||||
|
||||
return collection
|
||||
}
|
||||
@ -1,5 +0,0 @@
|
||||
import Collection from './components/PageCollection.js'
|
||||
|
||||
export * from '../shared/index.js'
|
||||
|
||||
export { Collection }
|
||||
@ -1,89 +0,0 @@
|
||||
/**
|
||||
* functions 文件。
|
||||
* 页面发起请求时,是以 文件名作为 接口的,
|
||||
* 如 当前文件名为 page_collection,
|
||||
* 那么客户端发起的请求接口应该是 {host}:{port}/{proxyPrefix}/page_collection
|
||||
*/
|
||||
// 引入这个包来提供类型支持
|
||||
import process from 'node:process'
|
||||
import type { Handler } from '@netlify/functions'
|
||||
import * as lean from 'leancloud-storage'
|
||||
|
||||
// 通过环境变量来获取 鉴权信息
|
||||
// 具体的配置,在开发环境中应该写在项目根目录的 `.env` 文件中
|
||||
// 在生产环境中应该在 netlify 控制台中 配置 环境变量
|
||||
// 同时,需要在插件的说明文档中 说明需要配置哪些 变量
|
||||
lean.init({
|
||||
appId: process.env.LEAN_CLOUD_APP_ID || '',
|
||||
appKey: process.env.LEAN_CLOUD_APP_KEY || '',
|
||||
masterKey: process.env.LEAN_CLOUD_MASTER_KEY || '',
|
||||
})
|
||||
|
||||
interface ResponseRes {
|
||||
statusCode: number
|
||||
body?: string
|
||||
message?: string
|
||||
}
|
||||
|
||||
function response(code: number, message: string, data?: Record<string, any>): ResponseRes {
|
||||
return {
|
||||
statusCode: 200,
|
||||
body: JSON.stringify({
|
||||
code,
|
||||
result: data || '',
|
||||
message,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
function successRes(data: Record<string, any>): ResponseRes {
|
||||
return response(200, 'success', data)
|
||||
}
|
||||
|
||||
function errorRes(message: string, code = 500): ResponseRes {
|
||||
return response(code, message)
|
||||
}
|
||||
|
||||
// 主要是为了 在 leancloud 中获取 所有权限,便于操作
|
||||
// 我在 leancloud 控制台中配置的安全策略,默认是所有用户不可读写
|
||||
// 所以需要在 functions 中用这种方式来获取权限。
|
||||
const useMasterKey = Boolean(process.env.LEAN_CLOUD_MASTER_KEY)
|
||||
|
||||
// netlify functions 的 functions 格式规范
|
||||
// 通过导出一个 handler 函数作为 钩子
|
||||
// event 中包含了 请求相关的信息,你可以通过 console.log(event) 查看具体信息
|
||||
export const handler: Handler = async (event) => {
|
||||
// body 即为 请求体
|
||||
const { url } = JSON.parse(event.body || '') || {}
|
||||
if (!url)
|
||||
return errorRes('params [url] not found')
|
||||
|
||||
// 出于安全考虑,你可能还需要在这里做 域名请求白名单的校验
|
||||
// 可以在 event.headers 中拿到相关 域名信息
|
||||
|
||||
// leancloud 相关这里就不解释了
|
||||
const query = new lean.Query('Page')
|
||||
const Page = lean.Object.extend('Page')
|
||||
try {
|
||||
query.equalTo('url', url)
|
||||
const current = await query.first({ useMasterKey })
|
||||
let page: lean.Object
|
||||
if (current)
|
||||
page = lean.Object.createWithoutData('Page', current.get('objectId'))
|
||||
|
||||
else
|
||||
page = new Page()
|
||||
|
||||
page.increment('visitCount', 1)
|
||||
page = await page.save(null, {
|
||||
useMasterKey,
|
||||
fetchWhenSave: true,
|
||||
})
|
||||
return successRes({
|
||||
visitCount: page.get('visitCount'),
|
||||
})
|
||||
}
|
||||
catch (e: any) {
|
||||
return errorRes(e.message, e.code || e.status || e.statusCode)
|
||||
}
|
||||
}
|
||||
@ -1,6 +0,0 @@
|
||||
import { pageCollectionPlugin } from './plugin.js'
|
||||
|
||||
export * from './plugin.js'
|
||||
export * from '../shared/index.js'
|
||||
|
||||
export default pageCollectionPlugin
|
||||
@ -1,47 +0,0 @@
|
||||
/**
|
||||
* 如果是一个 仅 提供 functions 支持的插件,
|
||||
* 基本上可以照搬本文件进行插件声明
|
||||
* 然后在此基础上进行修改
|
||||
*/
|
||||
|
||||
// 通过引入 'vuepress-plugin-netlify-functions' 插件,来为本插件提供
|
||||
// netlify functions 开发时支持
|
||||
import type { App, Plugin } from 'vuepress/core'
|
||||
import { getDirname, path } from 'vuepress/utils'
|
||||
import { useNetlifyFunctionsPlugin } from 'vuepress-plugin-netlify-functions'
|
||||
import type { PageCollectionOptions } from '../shared/index.js'
|
||||
|
||||
const __dirname = getDirname(import.meta.url)
|
||||
|
||||
export function pageCollectionPlugin(_options: PageCollectionOptions = {}): Plugin {
|
||||
return (app: App) => {
|
||||
const {
|
||||
// 客户端发起 functions 请求时的代理前缀
|
||||
// 默认是 /api
|
||||
// /api/* 的请求实际被转发到了 netlify functions 服务器的 /.netlify/functions/*
|
||||
proxyPrefix,
|
||||
// 在开发环境中,需要将 自定义到 functions 文件,注入到 netlify functions 服务中
|
||||
// 这样才能够被请求到
|
||||
preparePluginFunctions,
|
||||
// vuepress 构建生产包时,打包这些 functions文件到 vuepress dest中。
|
||||
generatePluginFunctions,
|
||||
} = useNetlifyFunctionsPlugin(app, {
|
||||
// 一般来说, 都是设置为 path.join(__dirname, 'functions')
|
||||
// 即是当前文件同级的 functions 目录
|
||||
// 这个目录的文件都会被监听,然后注入到 netlify functions 服务中
|
||||
directory: path.join(__dirname, 'functions'),
|
||||
})
|
||||
return {
|
||||
name: '@vuepress-plume/plugin-page-collection',
|
||||
define: () => ({
|
||||
// 将 proxyPrefix 注入到 客户端中
|
||||
// 以便获取使用
|
||||
__COLLECTION_PROXY_PREFIX__: proxyPrefix,
|
||||
}),
|
||||
clientConfigFile: path.resolve(__dirname, '../client/clientConfig.js'),
|
||||
// 不要忘了,需要在这里 定义好 钩子
|
||||
onPrepared: () => preparePluginFunctions(),
|
||||
onGenerated: () => generatePluginFunctions(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1 +0,0 @@
|
||||
export type PageCollectionOptions = Record<string, unknown>
|
||||
@ -1,8 +0,0 @@
|
||||
{
|
||||
"extends": "../tsconfig.build.json",
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src",
|
||||
"outDir": "./lib"
|
||||
},
|
||||
"include": ["./src"]
|
||||
}
|
||||
@ -10,9 +10,7 @@
|
||||
{ "path": "./plugin-caniuse/tsconfig.build.json" },
|
||||
{ "path": "./plugin-copy-code/tsconfig.build.json" },
|
||||
{ "path": "./plugin-iconify/tsconfig.build.json" },
|
||||
{ "path": "./plugin-netlify-functions/tsconfig.build.json" },
|
||||
{ "path": "./plugin-notes-data/tsconfig.build.json" },
|
||||
{ "path": "./plugin-page-collection/tsconfig.build.json" },
|
||||
{ "path": "./plugin-shikiji/tsconfig.build.json" },
|
||||
{ "path": "./plugin-content-update/tsconfig.build.json" },
|
||||
{ "path": "./plugin-search/tsconfig.build.json" },
|
||||
|
||||
6743
pnpm-lock.yaml
generated
6743
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -2,4 +2,3 @@ packages:
|
||||
- docs
|
||||
- theme
|
||||
- plugins/*
|
||||
- '!plugins/plugin-page-collection'
|
||||
|
||||
@ -19,9 +19,6 @@
|
||||
"vuepress-theme-plume": ["./theme/src/node/index.ts"],
|
||||
"vuepress-theme-plume/composables": ["./theme/src/client/composables/index.ts"],
|
||||
"@vuepress-plume/*/client": ["./plugins/*/src/client/index.ts"],
|
||||
"vuepress-plugin-netlify-functions": [
|
||||
"./plugins/plugin-netlify-functions/src/node/index.ts"
|
||||
],
|
||||
"vuepress-plugin-md-power": [
|
||||
"./plugins/plugin-md-power/src/node/index.ts"
|
||||
],
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user