client: optimize seo

This commit is contained in:
fantasticit 2022-05-22 10:33:08 +08:00
parent f6c5e72126
commit 3d637eda7b
19 changed files with 161 additions and 23 deletions

View File

@ -104,6 +104,12 @@ client:
assetPrefix: '/' assetPrefix: '/'
apiUrl: 'http://localhost:5002/api' apiUrl: 'http://localhost:5002/api'
collaborationUrl: 'ws://localhost:5003' collaborationUrl: 'ws://localhost:5003'
# 以下为页面 meta 配置
seoAppName: '云策文档'
seoDescription: '云策文档是一款开源知识管理工具。通过独立的知识库空间,结构化地组织在线协作文档,实现知识的积累与沉淀,促进知识的复用与流通。'
seoKeywords: '云策文档,协作,文档,前端面试题,fantasticit,https://github.com/fantasticit/think'
# 预先连接的来源,空格分割(比如图片存储服务器)
dnsPrefetch: '//wipi.oss-cn-shanghai.aliyuncs.com'
server: server:
prefix: '/api' prefix: '/api'

View File

@ -4,6 +4,12 @@ client:
assetPrefix: '/' assetPrefix: '/'
apiUrl: 'http://localhost:5002/api' apiUrl: 'http://localhost:5002/api'
collaborationUrl: 'ws://localhost:5003' collaborationUrl: 'ws://localhost:5003'
# 以下为页面 meta 配置
seoAppName: '云策文档'
seoDescription: '云策文档是一款开源知识管理工具。通过独立的知识库空间,结构化地组织在线协作文档,实现知识的积累与沉淀,促进知识的复用与流通。'
seoKeywords: '云策文档,协作,文档,前端面试题,fantasticit,https://github.com/fantasticit/think'
# 预先连接的来源,空格分割(比如图片存储服务器)
dnsPrefetch: '//wipi.oss-cn-shanghai.aliyuncs.com'
server: server:
prefix: '/api' prefix: '/api'

View File

@ -2,5 +2,76 @@
* 将流程图编辑器所需的资源拷贝到 .next 目录中配合 nginx 运行 * 将流程图编辑器所需的资源拷贝到 .next 目录中配合 nginx 运行
*/ */
const fs = require('fs-extra'); const fs = require('fs-extra');
const { getConfig } = require('@think/config');
const config = getConfig();
fs.copySync('./public', './.next'); const buildManifestJson = () => {
return JSON.stringify({
name: config.client.seoAppName,
short_name: config.client.seoAppName,
display: 'standalone',
start_url: '/',
theme_color: '#ffffff',
background_color: '#ffffff',
icons: [
{
src: '/icon72.png',
sizes: '72x72',
type: 'image/png',
},
{
src: '/icon96.png',
sizes: '96x96',
type: 'image/png',
},
{
src: '/icon120.png',
sizes: '120x120',
type: 'image/png',
},
{
src: '/icon128.png',
sizes: '128x128',
type: 'image/png',
},
{
src: '/icon144.png',
sizes: '144x144',
type: 'image/png',
},
{
src: '/icon152.png',
sizes: '152x152',
type: 'image/png',
},
{
src: '/icon180.png',
sizes: '180x180',
type: 'image/png',
},
{
src: '/icon192.png',
sizes: '192x192',
type: 'image/png',
},
{
src: '/icon384.png',
sizes: '384x384',
type: 'image/png',
},
{
src: '/icon512.png',
sizes: '512x512',
type: 'image/png',
},
],
});
};
fs.copySync('./public', './.next', {
filter: (src) => {
// 生产环境使用 diagram.min.js
return !/diagram.js$/.test(src);
},
});
fs.outputFileSync('./.next/manifest.json', buildManifestJson());

View File

@ -11,6 +11,10 @@ const nextConfig = semi({
SERVER_API_URL: config.client.apiUrl, SERVER_API_URL: config.client.apiUrl,
COLLABORATION_API_URL: config.client.collaborationUrl, COLLABORATION_API_URL: config.client.collaborationUrl,
ENABLE_ALIYUN_OSS: !!config.oss.aliyun.accessKeyId, ENABLE_ALIYUN_OSS: !!config.oss.aliyun.accessKeyId,
DNS_PREFETCH: (config.client.dnsPrefetch || '').split(' '),
SEO_APPNAME: config.client.seoAppName,
SEO_DESCRIPTION: config.client.seoDescription,
SEO_KEYWORDS: config.client.seoKeywords,
}, },
webpack: (config, { dev, isServer }) => { webpack: (config, { dev, isServer }) => {
config.resolve.plugins.push(new TsconfigPathsPlugin()); config.resolve.plugins.push(new TsconfigPathsPlugin());

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -5,29 +5,27 @@ import styles from './index.module.scss';
const { Text } = Typography; const { Text } = Typography;
export const LogoName = '云策文档'; export const LogoName = process.env.SEO_APPNAME;
export const LogoImage = () => { export const LogoImage = () => {
return ( return (
<Link href={'/'} as={'/'}> <Link href={'/'} as={'/'}>
<a style={{ width: 36, height: 36 }}> <a style={{ width: 36, height: 36 }}>
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" width="36" height="36"> <svg
<path xmlns="http://www.w3.org/2000/svg"
d="M512 959.948464A448.076077 448.076077 0 0 1 337.632578 99.243069a448.094728 448.094728 0 0 1 348.734844 825.553127 445.140995 445.140995 0 0 1-174.367422 35.152268z m0-876.27409c-236.180835 0-428.325626 192.144791-428.325626 428.305993s192.144791 428.335442 428.325626 428.335443 428.31581-192.144791 428.31581-428.335443S748.171019 83.674374 512 83.674374z" version="1.0"
width="36"
height="36"
viewBox="0 0 512 512"
preserveAspectRatio="xMidYMid meet"
>
<g
transform="translate(0.000000,512.000000) scale(0.100000,-0.100000)"
fill="var(--semi-color-primary)" fill="var(--semi-color-primary)"
></path> stroke="none"
<path >
d="M512 910.179685a396.982093 396.982093 0 1 1 154.989992-31.294452 395.597991 395.597991 0 0 1-154.989992 31.294452z m0-786.552859c-214.152997 0-388.373174 174.220177-388.373174 388.353541s174.220177 388.38299 388.373174 388.38299 388.363357-174.220177 388.363357-388.38299-174.210361-388.353541-388.363357-388.353541z" <path d="M880 4799 c-85 -8 -208 -39 -235 -59 -5 -4 -28 -13 -49 -20 -54 -17 -179 -142 -196 -196 -7 -21 -16 -43 -20 -49 -25 -36 -51 -144 -60 -250 -14 -169 -13 -3182 1 -3335 9 -100 37 -215 59 -245 4 -5 13 -28 20 -49 17 -54 142 -179 196 -196 21 -7 44 -16 49 -20 36 -25 144 -51 250 -60 164 -13 3180 -13 3335 0 101 9 211 36 245 60 6 4 28 13 49 20 54 17 179 142 196 196 7 21 16 44 20 49 22 30 50 145 59 245 14 153 15 3166 1 3335 -9 106 -35 214 -60 250 -4 6 -13 28 -20 49 -17 54 -142 179 -196 196 -21 7 -43 16 -49 20 -30 22 -145 50 -245 59 -139 13 -3205 13 -3350 0z m2418 -1532 c281 -282 512 -516 512 -521 0 -9 -27 -39 -174 -196 -39 -42 -109 -118 -156 -170 -47 -52 -87 -97 -90 -100 -3 -3 -43 -45 -90 -95 -46 -49 -116 -124 -154 -165 -39 -42 -105 -113 -146 -159 -41 -46 -91 -100 -110 -120 -45 -48 -248 -266 -286 -309 -29 -31 -35 -33 -156 -47 -69 -8 -220 -19 -334 -25 -115 -6 -238 -15 -274 -20 -82 -12 -520 -34 -527 -27 -6 7 16 328 27 389 5 26 14 116 20 200 6 84 15 178 20 208 5 30 14 120 20 200 15 211 18 226 54 263 35 36 281 267 366 343 30 27 68 63 85 79 17 17 87 82 155 145 68 63 140 131 160 150 20 19 81 76 136 125 54 50 135 124 179 166 200 188 209 196 240 198 6 1 241 -230 523 -512z" />
fill="var(--semi-color-primary)" </g>
></path>
<path
d="M509.172898 357.196518m-70.167108 0a70.167108 70.167108 0 1 0 140.334215 0 70.167108 70.167108 0 1 0-140.334215 0Z"
fill="var(--semi-color-primary)"
></path>
<path
d="M427.559952 441.450056s34.219717 33.031941 77.411558 32.246635 83.919782-32.266268 83.919782-32.266268l99.488477 377.928602s-27.66241-20.7419-47.245983-19.200737-46.519575 41.15986-65.690863 40.001534-45.70482-54.971433-58.770351-54.156678-40.718126 57.661107-62.225699 54.186127-39.432187-48.168718-67.094597-47.118371-44.55631 22.577553-44.55631 22.577553zM509.172898 183.653668l-21.674451 68.26274h43.339085l-21.664634-68.26274zM682.715748 357.196518l-68.26274-21.664634v43.339085l68.26274-21.674451zM631.886805 234.482611l-63.590168 32.95341 30.636758 30.636758 32.95341-63.590168zM386.449174 234.482611l32.95341 63.590168 30.636758-30.636758-63.590168-32.95341zM335.620231 357.196518l68.26274 21.674451v-43.339085l-68.26274 21.664634z"
fill="var(--semi-color-primary)"
></path>
</svg> </svg>
</a> </a>
</Link> </Link>

View File

@ -16,9 +16,6 @@ export const Seo: React.FC<IProps> = ({ title, needTitleSuffix = true }) => {
return ( return (
<Helmet> <Helmet>
<title>{needTitleSuffix ? buildTitle(title) : title}</title> <title>{needTitleSuffix ? buildTitle(title) : title}</title>
<meta name="viewport" content="width=device-width,initial-scale=1.0,viewport-fit=cover,maximum-scale=1" />
<meta name="keyword" content={`云策文档 协作 文档 fantasticit`} />
<meta name="description" content={`云策文档 协作 文档 fantasticit`} />
</Helmet> </Helmet>
); );
}; };

View File

@ -12,7 +12,31 @@ function MyApp({ Component, pageProps }: AppProps) {
return ( return (
<> <>
<Head> <Head>
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta
name="viewport"
content="minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no, user-scalable=no, viewport-fit=cover"
/>
<meta charSet="utf-8" />
<meta name="description" content={process.env.SEO_DESCRIPTION} />
<meta name="keywords" content={process.env.SEO_KEYWORDS}></meta>
<meta name="application-name" content={process.env.SEO_APPNAME} />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="default" />
<meta name="apple-mobile-web-app-title" content={process.env.SEO_APPNAME} />
<meta name="description" content={process.env.SEO_DESCRIPTION} />
<meta name="format-detection" content="telephone=no" />
<meta name="mobile-web-app-capable" content="yes" />
<meta name="msapplication-TileColor" content="#ffffff" />
<meta name="msapplication-tap-highlight" content="no" />
<meta name="theme-color" content="#ffffff" />
<meta property="og:type" content="website" />
<meta property="og:title" content={process.env.SEO_APPNAME} />
<meta property="og:description" content={process.env.SEO_DESCRIPTION} />
<meta property="og:site_name" content={process.env.SEO_APPNAME} />
<link rel="manifest" href="/manifest.json" />
{((process.env.DNS_PREFETCH || []) as string[]).map((url) => (
<link key={url} rel="dns-prefetch" href={url} />
))}
</Head> </Head>
<Theme.Provider> <Theme.Provider>
<Component {...pageProps} /> <Component {...pageProps} />

View File

@ -291,6 +291,7 @@ importers:
bcryptjs: ^2.4.3 bcryptjs: ^2.4.3
class-transformer: ^0.5.1 class-transformer: ^0.5.1
class-validator: ^0.13.2 class-validator: ^0.13.2
compression: ^1.7.4
date-fns: ^2.28.0 date-fns: ^2.28.0
eslint: ^8.14.0 eslint: ^8.14.0
eslint-config-prettier: ^8.5.0 eslint-config-prettier: ^8.5.0
@ -346,6 +347,7 @@ importers:
bcryptjs: 2.4.3 bcryptjs: 2.4.3
class-transformer: 0.5.1 class-transformer: 0.5.1
class-validator: 0.13.2 class-validator: 0.13.2
compression: 1.7.4
date-fns: 2.28.0 date-fns: 2.28.0
express: 4.17.2 express: 4.17.2
express-rate-limit: 6.2.0_express@4.17.2 express-rate-limit: 6.2.0_express@4.17.2
@ -4302,6 +4304,11 @@ packages:
readable-stream: 1.1.14 readable-stream: 1.1.14
dev: false dev: false
/bytes/3.0.0:
resolution: {integrity: sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=}
engines: {node: '>= 0.8'}
dev: false
/bytes/3.1.1: /bytes/3.1.1:
resolution: {integrity: sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==} resolution: {integrity: sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==}
engines: {node: '>= 0.8'} engines: {node: '>= 0.8'}
@ -4604,6 +4611,26 @@ packages:
resolution: {integrity: sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==} resolution: {integrity: sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==}
dev: true dev: true
/compressible/2.0.18:
resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==}
engines: {node: '>= 0.6'}
dependencies:
mime-db: 1.51.0
dev: false
/compression/1.7.4:
resolution: {integrity: sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==}
engines: {node: '>= 0.8.0'}
dependencies:
accepts: 1.3.7
bytes: 3.0.0
compressible: 2.0.18
debug: 2.6.9
on-headers: 1.0.2
safe-buffer: 5.1.2
vary: 1.1.2
dev: false
/compute-scroll-into-view/1.0.17: /compute-scroll-into-view/1.0.17:
resolution: {integrity: sha512-j4dx+Fb0URmzbwwMUrhqWM2BEWHdFGx+qZ9qqASHRPqvTYdqvWnHg0H1hIbcyLnvgnoNAVMlwkepyqM3DaIFUg==} resolution: {integrity: sha512-j4dx+Fb0URmzbwwMUrhqWM2BEWHdFGx+qZ9qqASHRPqvTYdqvWnHg0H1hIbcyLnvgnoNAVMlwkepyqM3DaIFUg==}
dev: false dev: false
@ -6042,7 +6069,7 @@ packages:
dependencies: dependencies:
'@tootallnate/once': 1.1.2 '@tootallnate/once': 1.1.2
data-uri-to-buffer: 3.0.1 data-uri-to-buffer: 3.0.1
debug: 4.3.3 debug: 4.3.4
file-uri-to-path: 2.0.0 file-uri-to-path: 2.0.0
fs-extra: 8.1.0 fs-extra: 8.1.0
ftp: 0.3.10 ftp: 0.3.10
@ -8277,6 +8304,11 @@ packages:
ee-first: 1.1.1 ee-first: 1.1.1
dev: false dev: false
/on-headers/1.0.2:
resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==}
engines: {node: '>= 0.8'}
dev: false
/once/1.4.0: /once/1.4.0:
resolution: {integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E=} resolution: {integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E=}
dependencies: dependencies: