├── .github
├── CONTRIBUTING.md
└── ISSUE_TEMPLATE
│ ├── ------feature-request-.md
│ └── -----bug-report-.md
├── .gitignore
├── .husky
└── pre-commit
├── .npmrc
├── .vscode
├── extensions.json
├── global.code-snippets
└── settings.json
├── README.md
├── app.config.ts
├── app.vue
├── assets
├── img
│ ├── aside
│ │ ├── design.png
│ │ └── document.png
│ └── beam
│ │ ├── docs_bg.png
│ │ ├── fill.jpg
│ │ ├── home_bg.jpg
│ │ ├── pink.jpg
│ │ └── sky.jpg
└── style
│ └── base.css
├── components
├── AppHeader.vue
├── content
│ ├── Card.vue
│ ├── Image.vue
│ └── Tabs.vue
└── navigation
│ ├── NavigationAside.vue
│ └── NavigationToc.vue
├── composables
├── useDevice.ts
├── useFormatHash.ts
├── useHeaderInfo.ts
├── useLocale.ts
├── useOrganizeAside.ts
├── useSetAppHead.ts
└── useToc.ts
├── content
├── concept
│ ├── 10.documentation.md
│ ├── 100.html
│ │ └── _dir.yml
│ ├── 200.css
│ │ ├── 1.attribute-calc.md
│ │ └── _dir.yml
│ ├── 300.js
│ │ ├── 1.es5.md
│ │ ├── 2.prototype-chain.md
│ │ ├── 3.event-loop.md
│ │ ├── 5.cjs-esm.md
│ │ ├── 7.design-pattern.md
│ │ └── _dir.yml
│ ├── 400.browser
│ │ ├── 1.rendering-principle.md
│ │ └── _dir.yml
│ ├── 500.network
│ │ └── _dir.yml
│ ├── 600.cli
│ │ └── _dir.yml
│ └── 700.project
│ │ └── _dir.yml
└── docs
│ ├── 10.documentation.md
│ ├── 100.standard-directory
│ ├── 1.fe-directory.md
│ ├── 3.linux-directory.md
│ └── _dir.yml
│ ├── 1000.standard-analyse
│ ├── 1.chrome.md
│ ├── 2.user-traffic.md
│ └── _dir.yml
│ ├── 20.design.md
│ ├── 200.standard-code
│ ├── .5.tsconfig.md
│ ├── 1.vscode.md
│ ├── 2.eslint.md
│ ├── 3.prettier.md
│ ├── 4.stylelint.md
│ └── _dir.yml
│ ├── 2000.toolbox
│ ├── 1.mac.md
│ ├── 2.windows.md
│ ├── 3.tv.md
│ └── _dir.yml
│ ├── 300.standard-commit
│ ├── 1.husky-lintstaged.md
│ ├── 2.commitizen-commitlint.md
│ ├── 3.changelog.md
│ ├── 4.git.md
│ └── _dir.yml
│ ├── 400.standard-dev
│ ├── 0.html.md
│ ├── 1.var.md
│ ├── 2.notes.md
│ ├── 3.mock.md
│ └── _dir.yml
│ ├── 500.stanard-buiild
│ ├── 1.package.md
│ ├── 2.build.md
│ └── _dir.yml
│ ├── 600.standard-monitor
│ ├── 1.buried.md
│ └── _dir.yml
│ ├── 700.standard-optimize
│ ├── 1.css.md
│ ├── 2.js.md
│ ├── 3.resource.md
│ ├── 3.vue.md
│ ├── 4.mini-program.md
│ ├── 6.webpack.md
│ ├── 7.vite.md
│ ├── 9.network.md
│ └── _dir.yml
│ ├── 800.standard-test
│ ├── 1.unit.md
│ ├── 2.automation.md
│ ├── 3.e2e.md
│ └── _dir.yml
│ └── 900.standard-deploy
│ ├── 1.server.md
│ ├── 14.node.md
│ ├── 15.cicd.md
│ ├── 16.devops.md
│ ├── 2.applet.md
│ ├── 3.app.md
│ └── _dir.yml
├── error.vue
├── eslint.config.mjs
├── layouts
└── default.vue
├── license
├── middleware
├── analytics.global.ts
└── auth.ts
├── nuxt.config.ts
├── package.json
├── pages
├── concept
│ └── [...slug].vue
├── docs
│ └── [...slug].vue
└── index.vue
├── pnpm-lock.yaml
├── public
├── content
│ └── concept
│ │ └── js_prototype_chain.png
├── favicon.ico
└── logo.png
├── tsconfig.json
├── types
└── navigation.ts
└── uno.config.ts
/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # 贡献指南
2 |
3 | ## 先决条件
4 | - [Nuxt prerequisites](https://nuxt.com/docs/getting-started/installation#prerequisites)
5 |
6 | ## 开发
7 | ### markdown
8 | - 可参考 [.vscode/global.code-snippets](/.vscode/global.code-snippets) 快捷生成代码文件
9 |
10 | ## 是否通过代码提交规范
11 | - [x] eslint 校验
12 |
13 | ## 提交 PR
14 | - fork 本仓库,在自己仓库基于 master 分支创建专用分支用于提交更改。
15 | - commit 规范遵循 Vue 仓库 [Git Commit Message Convention](https://github.com/vuejs/vue/blob/dev/.github/COMMIT_CONVENTION.md)。
16 | - 提交之前确保进行了完善的测试。
17 | - 确保 PR 提交到 master 分支。
18 | - 修复 Bug 请提供详细的描述信息,或链接到对应的 issue。
19 | - 提交新功能请阐明起用途以及提交到主仓库的必要性,最好事先仓库主要成员商议后再进行。
20 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/------feature-request-.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 建议新功能(Feature Request)
3 | about: 对 系统 提出改善建议
4 | title: ''
5 | labels: enhancement
6 | assignees: ''
7 | ---
8 |
9 | **新功能描述** 简洁描述你希望补充完善的增强功能
10 |
11 | **现状及问题** [当前现状及由此导致的不便]
12 |
13 | **尝试方案** [如果你有尝试绕开或其它解决方案,在这里描述你的建议方案]
14 |
15 | **补充信息** [其它你认为有参考价值的信息]
16 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/-----bug-report-.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 报告问题(Bug report)
3 | about: 详细描述你遇到的问题并寻求社区帮助
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 | ---
8 |
9 | **问题描述** [问题描述:尽可能简洁清晰地把问题描述清楚]
10 |
11 | **复现步骤** [复现问题的步骤]
12 |
13 | 1. 启动 '...'
14 | 2. 点击 '....'
15 | 3. 查看
16 |
17 | [或者可以直接贴源代码]
18 |
19 | **预期结果** [使用简洁清晰的语言描述你希望生效的预期结果]
20 |
21 | **实际结果** [这里请贴上你的报错截图或文字]
22 |
23 | **系统信息:**
24 |
25 | - 操作系统 [如 Mac 12.5]
26 | - 系统版本 [如 Version 1.0.0]
27 | - 设备信息 [如 Google Chrome 104.0.5112.101]
28 |
29 | **补充信息** [可选] [根据你的分析,出现这个问题的原因可能在哪里?]
30 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Nuxt dev/build outputs
2 | .output
3 | .data
4 | .nuxt
5 | .nitro
6 | .cache
7 | dist
8 |
9 | # Node dependencies
10 | node_modules
11 |
12 | # Logs
13 | logs
14 | *.log
15 |
16 | # Misc
17 | .DS_Store
18 | .fleet
19 | .idea
20 |
21 | # Local env files
22 | # .env
23 | # .env.*
24 | # !.env.example
25 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | npx lint-staged
2 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | engine-strict=true
2 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | // themes & icons
4 | "antfu.theme-vitesse",
5 | "antfu.icons-carbon",
6 | "file-icons.file-icons",
7 | "Catppuccin.catppuccin-vsc-icons",
8 |
9 | // essential
10 | "Vue.Official",
11 | "octref.vetur",
12 | // "Nuxtr.nuxtr-vscode",
13 | "nuxt.mdc",
14 | "antfu.vite",
15 | "antfu.unocss",
16 | "antfu.iconify",
17 | "dbaeumer.vscode-eslint",
18 |
19 | // life savers!
20 | "GitHub.copilot",
21 | "github.copilot-chat",
22 | "intellsmi.comment-translate",
23 | "ms-ceintl.vscode-language-pack-zh-hans",
24 | "eamodio.gitlens",
25 | "EditorConfig.EditorConfig",
26 |
27 | // project tool
28 | "jock.svg",
29 | "lokalise.i18n-ally",
30 |
31 | // up to you
32 | "antfu.file-nesting",
33 | "antfu.browse-lite",
34 | "ritwickdey.liveserver",
35 | "usernamehw.errorlens",
36 | "streetsidesoftware.code-spell-checker",
37 | "wayou.vscode-todo-highlight",
38 | "vincaslt.highlight-matching-tag"
39 | // "naumovs.color-highlight",
40 | // "WakaTime.vscode-wakatime",
41 | // "github.vscode-github-actions",
42 | // "GitHub.vscode-pull-request-github",
43 | ]
44 | }
45 |
--------------------------------------------------------------------------------
/.vscode/global.code-snippets:
--------------------------------------------------------------------------------
1 | {
2 | "uniapp-vue2-template": {
3 | "scope": "vue",
4 | "prefix": "vue",
5 | "description": "Uniapp Vue2 Template",
6 | "body": [
7 | "",
8 | " ",
9 | "",
10 | "",
11 | "",
12 | "",
21 | "",
22 | "",
23 | "",
24 | ]
25 | },
26 | "vue2-template": {
27 | "scope": "vue",
28 | "prefix": "vue",
29 | "description": "Vue2 Template",
30 | "body": [
31 | "",
32 | " ",
33 | "",
34 | "",
35 | "",
36 | "",
45 | "",
46 | "",
47 | "",
48 | ]
49 | },
50 | "vue3-template": {
51 | "scope": "vue",
52 | "prefix": "vue",
53 | "description": "Vue3 Template",
54 | "body": [
55 | "",
62 | "",
63 | "",
64 | "",
65 | " ",
66 | "",
67 | "",
68 | "",
69 | "",
70 | ]
71 | },
72 | "vue2-mixins": {
73 | "scope": "javascript,typescript",
74 | "prefix": "mixins",
75 | "description": "Vue2 Mixins",
76 | "body": [
77 | "export default {",
78 | " data() {",
79 | " return {}",
80 | " },",
81 | "",
82 | " methods: {},",
83 | "}",
84 | ]
85 | },
86 | "markdown-blog-template": {
87 | "scope": "markdown",
88 | "prefix": "md",
89 | "description": "Blog Template",
90 | "body": [
91 | "---",
92 | "title: ''",
93 | "description: ''",
94 | "navigation:",
95 | " icon: ''",
96 | " title: ''",
97 | "---",
98 | ""
99 | ]
100 | },
101 | "markdown-readme-template": {
102 | "scope": "markdown",
103 | "prefix": "md",
104 | "description": "README Template",
105 | "body": [
106 | "
Welcome to X 👋
",
107 | "",
108 | "
",
109 | "
",
110 | "",
111 | "> Description of the X",
112 | "",
113 | "### 🏠 [Homepage]()",
114 | "",
115 | "### ✨ [Demo]()",
116 | "",
117 | "## Install",
118 | "",
119 | "```sh",
120 | "```",
121 | "",
122 | "## Usage",
123 | "",
124 | "```sh",
125 | "```",
126 | "",
127 | "## Run tests",
128 | "",
129 | "```sh",
130 | "```",
131 | "",
132 | "## 📝 License",
133 | "",
134 | "Copyright © 2024 []().
",
135 | "This project is [MIT]() licensed."
136 | ]
137 | },
138 | "markdown-api-table": {
139 | "scope": "markdown",
140 | "prefix": "md",
141 | "description": "Markdown Api Table",
142 | "body": [
143 | "",
144 | "",
145 | "",
146 | "",
147 | "### API",
148 | "",
149 | "Description",
150 | "",
151 | " | ",
152 | " ",
153 | "",
154 | "```ts",
155 | "// code block",
156 | "```",
157 | "",
158 | " | ",
159 | "
",
160 | "
",
161 | ],
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | // ========== Visuals ==========
3 | "editor.cursorSmoothCaretAnimation": "on",
4 | "editor.fontFamily": "Input Mono, monospace",
5 | "editor.guides.bracketPairs": "active",
6 | "editor.lineNumbers": "interval",
7 | "editor.renderWhitespace": "boundary",
8 | "window.autoDetectColorScheme": true,
9 | "workbench.colorTheme": "Vitesse Dark",
10 | "workbench.editor.tabActionLocation": "left",
11 | "workbench.fontAliasing": "antialiased",
12 | "workbench.iconTheme": "catppuccin-mocha",
13 | "workbench.list.smoothScrolling": true,
14 | "workbench.preferredDarkColorTheme": "Vitesse Dark",
15 | "workbench.preferredLightColorTheme": "Vitesse Light",
16 | "workbench.productIconTheme": "icons-carbon",
17 | "workbench.sideBar.location": "left",
18 | "workbench.startupEditor": "newUntitledFile",
19 | "workbench.tree.expandMode": "singleClick",
20 | "workbench.tree.indent": 10,
21 |
22 | // ========== Editor ==========
23 | "debug.onTaskErrors": "debugAnyway",
24 | "diffEditor.ignoreTrimWhitespace": false,
25 | "editor.wordSeparators": "`~!@#%^&*()=+[{]}\\|;:'\",.<>/?",
26 | "editor.find.addExtraSpaceOnTop": false,
27 | "editor.inlineSuggest.enabled": true,
28 | "editor.multiCursorModifier": "ctrlCmd",
29 | "editor.suggestSelection": "first",
30 | "editor.tabSize": 2,
31 | "editor.unicodeHighlight.invisibleCharacters": false,
32 | "editor.stickyScroll.enabled": true,
33 | "editor.hover.sticky": true,
34 | "editor.codeActionsOnSave": {
35 | "source.fixAll": "never",
36 | "source.fixAll.eslint": "explicit",
37 | "source.organizeImports": "never"
38 | },
39 | "explorer.confirmDelete": false,
40 | "explorer.confirmDragAndDrop": false,
41 | "files.eol": "\n",
42 | "files.insertFinalNewline": true,
43 | "files.simpleDialog.enable": true,
44 | "git.autofetch": true,
45 | "git.confirmSync": false,
46 | "git.enableSmartCommit": true,
47 | "git.untrackedChanges": "separate",
48 | "scm.diffDecorationsGutterWidth": 2,
49 | "terminal.integrated.cursorBlinking": true,
50 | "terminal.integrated.cursorStyle": "line",
51 | "terminal.integrated.fontWeight": "300",
52 | "terminal.integrated.persistentSessionReviveProcess": "never",
53 | "terminal.integrated.tabs.enabled": true,
54 | "workbench.editor.closeOnFileDelete": true,
55 | "workbench.editor.highlightModifiedTabs": true,
56 | "workbench.editor.limit.enabled": true,
57 | "workbench.editor.limit.perEditorGroup": true,
58 | "workbench.editor.limit.value": 5,
59 | "search.exclude": {
60 | "**/*.snap": true,
61 | "**/*.svg": true,
62 | "**/.git": true,
63 | "**/.github": false,
64 | "**/.nuxt": true,
65 | "**/.output": true,
66 | "**/.pnpm": true,
67 | "**/.vscode": true,
68 | "**/.yarn": true,
69 | "**/assets": true,
70 | "**/bower_components": true,
71 | "**/dist/**": true,
72 | "**/logs": true,
73 | "**/node_modules": true,
74 | "**/out/**": true,
75 | "**/package-lock.json": true,
76 | "**/pnpm-lock.yaml": true,
77 | "**/public": true,
78 | "**/temp": true,
79 | "**/yarn.lock": true,
80 | "**/CHANGELOG*": true,
81 | "**/LICENSE*": true
82 | },
83 | "[markdown]": {
84 | "editor.quickSuggestions": {
85 | "other": true,
86 | "comments": true,
87 | "strings": true
88 | }
89 | },
90 |
91 | // ========== Global Level Config, needs to put in User Settings ==========
92 | "window.dialogStyle": "custom",
93 | "window.nativeTabs": true, // this is great, macOS only
94 | "window.title": "${rootName}", // this make tabs more readable
95 | "window.titleBarStyle": "custom",
96 | "extensions.autoUpdate": "onlyEnabledExtensions",
97 |
98 | // ========== Extension configs ==========
99 | "emmet.showSuggestionsAsSnippets": true,
100 | "emmet.triggerExpansionOnTab": false,
101 | "errorLens.enabledDiagnosticLevels": [
102 | "warning",
103 | "error"
104 | ],
105 | "errorLens.excludeBySource": [
106 | "cSpell",
107 | "Grammarly",
108 | "eslint"
109 | ],
110 |
111 | // ESLint config: https://github.com/antfu/eslint-config
112 | "eslint.experimental.useFlatConfig": true,
113 | "eslint.codeAction.showDocumentation": {
114 | "enable": true
115 | },
116 | "eslint.quiet": true,
117 | // Silent the stylistic rules in you IDE, but still auto fix them
118 | "eslint.rules.customizations": [
119 | { "rule": "style/*", "severity": "off" },
120 | { "rule": "format/*", "severity": "off" },
121 | { "rule": "*-indent", "severity": "off" },
122 | { "rule": "*-spacing", "severity": "off" },
123 | { "rule": "*-spaces", "severity": "off" },
124 | { "rule": "*-order", "severity": "off" },
125 | { "rule": "*-dangle", "severity": "off" },
126 | { "rule": "*-newline", "severity": "off" },
127 | { "rule": "*quotes", "severity": "off" },
128 | { "rule": "*semi", "severity": "off" }
129 | ],
130 | "eslint.validate": [
131 | "javascript",
132 | "javascriptreact",
133 | "typescript",
134 | "typescriptreact",
135 | "vue",
136 | "html",
137 | "markdown",
138 | "json",
139 | "jsonc",
140 | "yaml",
141 | "toml"
142 | ],
143 |
144 | "github.copilot.enable": {
145 | "*": true,
146 | "markdown": true,
147 | "plaintext": false
148 | },
149 | "cSpell.allowCompoundWords": true,
150 | "cSpell.language": "en,en-US",
151 | "css.lint.hexColorLength": "ignore",
152 | // "githubIssues.workingIssueFormatScm": "#${issueNumberLabel}",
153 | // "githubPullRequests.fileListLayout": "tree",
154 | "gitlens.codeLens.authors.enabled": false,
155 | "gitlens.codeLens.enabled": false,
156 | "gitlens.codeLens.recentChange.enabled": false,
157 | "gitlens.menus": {
158 | "editor": {
159 | "blame": false,
160 | "clipboard": true,
161 | "compare": true,
162 | "history": false,
163 | "remote": false
164 | },
165 | "editorGroup": {
166 | "blame": true,
167 | "compare": false
168 | },
169 | "editorTab": {
170 | "clipboard": true,
171 | "compare": true,
172 | "history": true,
173 | "remote": true
174 | },
175 | "explorer": {
176 | "clipboard": true,
177 | "compare": true,
178 | "history": true,
179 | "remote": true
180 | },
181 | "scm": {
182 | "authors": true
183 | },
184 | "scmGroup": {
185 | "compare": true,
186 | "openClose": true,
187 | "stash": true
188 | },
189 | "scmGroupInline": {
190 | "stash": true
191 | },
192 | "scmItem": {
193 | "clipboard": true,
194 | "compare": true,
195 | "history": true,
196 | "remote": false,
197 | "stash": true
198 | }
199 | },
200 | "i18n-ally.autoDetection": false,
201 | "i18n-ally.displayLanguage": "en",
202 | "i18n-ally.ignoredLocales": [],
203 | "iconify.annotations": true,
204 | "iconify.inplace": true,
205 | "svg.preview.mode": "svg",
206 |
207 | // I only use Prettier for manually formatting
208 | // "prettier.enable": false,
209 | // "prettier.printWidth": 200,
210 | // "prettier.semi": false,
211 | // "prettier.singleQuote": true,
212 |
213 | // ========== File Nesting ==========
214 | // this might not be up to date with the repo, please check yourself
215 | // https://github.com/antfu/vscode-file-nesting-config
216 | "explorer.fileNesting.enabled": true,
217 | "explorer.fileNesting.expand": false,
218 | "explorer.fileNesting.patterns": {
219 | "*.asax": "$(capture).*.cs, $(capture).*.vb",
220 | "*.ascx": "$(capture).*.cs, $(capture).*.vb",
221 | "*.ashx": "$(capture).*.cs, $(capture).*.vb",
222 | "*.aspx": "$(capture).*.cs, $(capture).*.vb",
223 | "*.bloc.dart": "$(capture).event.dart, $(capture).state.dart",
224 | "*.c": "$(capture).h",
225 | "*.cc": "$(capture).hpp, $(capture).h, $(capture).hxx",
226 | "*.cjs": "$(capture).cjs.map, $(capture).*.cjs, $(capture)_*.cjs",
227 | "*.component.ts": "$(capture).component.html, $(capture).component.spec.ts, $(capture).component.css, $(capture).component.scss, $(capture).component.sass, $(capture).component.less",
228 | "*.cpp": "$(capture).hpp, $(capture).h, $(capture).hxx",
229 | "*.cs": "$(capture).*.cs",
230 | "*.cshtml": "$(capture).cshtml.cs",
231 | "*.csproj": "*.config, *proj.user, appsettings.*, bundleconfig.json",
232 | "*.css": "$(capture).css.map, $(capture).*.css",
233 | "*.cxx": "$(capture).hpp, $(capture).h, $(capture).hxx",
234 | "*.dart": "$(capture).freezed.dart, $(capture).g.dart",
235 | "*.ex": "$(capture).html.eex, $(capture).html.heex, $(capture).html.leex",
236 | "*.go": "$(capture)_test.go",
237 | "*.java": "$(capture).class",
238 | "*.js": "$(capture).js.map, $(capture).*.js, $(capture)_*.js",
239 | "*.jsx": "$(capture).js, $(capture).*.jsx, $(capture)_*.js, $(capture)_*.jsx",
240 | "*.master": "$(capture).*.cs, $(capture).*.vb",
241 | "*.mjs": "$(capture).mjs.map, $(capture).*.mjs, $(capture)_*.mjs",
242 | "*.module.ts": "$(capture).resolver.ts, $(capture).controller.ts, $(capture).service.ts",
243 | "*.pubxml": "$(capture).pubxml.user",
244 | "*.resx": "$(capture).*.resx, $(capture).designer.cs, $(capture).designer.vb",
245 | "*.tex": "$(capture).acn, $(capture).acr, $(capture).alg, $(capture).aux, $(capture).bbl, $(capture).blg, $(capture).fdb_latexmk, $(capture).fls, $(capture).glg, $(capture).glo, $(capture).gls, $(capture).idx, $(capture).ind, $(capture).ist, $(capture).lof, $(capture).log, $(capture).lot, $(capture).out, $(capture).pdf, $(capture).synctex.gz, $(capture).toc, $(capture).xdv",
246 | "*.ts": "$(capture).js, $(capture).d.ts.map, $(capture).*.ts, $(capture)_*.js, $(capture)_*.ts",
247 | "*.tsx": "$(capture).ts, $(capture).*.tsx, $(capture)_*.ts, $(capture)_*.tsx",
248 | "*.vbproj": "*.config, *proj.user, appsettings.*, bundleconfig.json",
249 | "*.vue": "$(capture).*.ts, $(capture).*.js, $(capture).story.vue",
250 | "*.xaml": "$(capture).xaml.cs",
251 | "+layout.svelte": "+layout.ts,+layout.ts,+layout.js,+layout.server.ts,+layout.server.js,+layout.gql",
252 | "+page.svelte": "+page.server.ts,+page.server.js,+page.ts,+page.js,+page.gql",
253 | ".clang-tidy": ".clang-format, .clangd, compile_commands.json",
254 | ".env": "*.env, .env.*, .envrc, env.d.ts",
255 | ".gitignore": ".gitattributes, .gitmodules, .gitmessage, .mailmap, .git-blame*",
256 | ".project": ".classpath",
257 | "//": "Last update at 4/29/2023, 2:04:58 PM",
258 | "BUILD.bazel": "*.bzl, *.bazel, *.bazelrc, bazel.rc, .bazelignore, .bazelproject, WORKSPACE",
259 | "CMakeLists.txt": "*.cmake, *.cmake.in, .cmake-format.yaml, CMakePresets.json",
260 | "I*.cs": "$(capture).cs",
261 | "artisan": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, server.php, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, webpack.config.*, webpack.mix.js, windi.config.*",
262 | "astro.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*",
263 | "cargo.toml": ".clippy.toml, .rustfmt.toml, cargo.lock, clippy.toml, cross.toml, rust-toolchain.toml, rustfmt.toml",
264 | "composer.json": ".php*.cache, composer.lock, phpunit.xml*, psalm*.xml",
265 | "default.nix": "shell.nix",
266 | "deno.json*": "*.env, .env.*, .envrc, api-extractor.json, deno.lock, env.d.ts, import-map.json, import_map.json, jsconfig.*, tsconfig.*, tsdoc.*",
267 | "dockerfile": ".dockerignore, docker-compose.*, dockerfile*",
268 | "flake.nix": "flake.lock",
269 | "gatsby-config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, gatsby-browser.*, gatsby-node.*, gatsby-ssr.*, gatsby-transformer.*, histoire.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*",
270 | "gemfile": ".ruby-version, gemfile.lock",
271 | "go.mod": ".air*, go.sum",
272 | "go.work": "go.work.sum",
273 | "mix.exs": ".credo.exs, .dialyzer_ignore.exs, .formatter.exs, .iex.exs, .tool-versions, mix.lock",
274 | "next.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, next-env.d.ts, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*",
275 | "nuxt.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*",
276 | "package.json": ".browserslist*, .circleci*, .commitlint*, .cz-config.js, .czrc, .dlint.json, .dprint.json, .editorconfig, .eslint*, .firebase*, .flowconfig, .github*, .gitlab*, .gitpod*, .huskyrc*, .jslint*, .lintstagedrc*, .markdownlint*, .node-version, .nodemon*, .npm*, .nvmrc, .pm2*, .pnp.*, .pnpm*, .prettier*, .releaserc*, .sentry*, .simple-git-hooks*, .stackblitz*, .styleci*, .stylelint*, .tazerc*, .textlint*, .tool-versions, .travis*, .versionrc*, .vscode*, .watchman*, .xo-config*, .yamllint*, .yarnrc*, Procfile, apollo.config.*, appveyor*, azure-pipelines*, bower.json, build.config.*, commitlint*, crowdin*, dangerfile*, dlint.json, dprint.json, eslint*, firebase.json, grunt*, gulp*, jenkins*, lerna*, lint-staged*, nest-cli.*, netlify*, nodemon*, npm-shrinkwrap.json, nx.*, package-lock.json, package.nls*.json, phpcs.xml, pm2.*, pnpm*, prettier*, pullapprove*, pyrightconfig.json, release-tasks.sh, release.config.*, renovate*, rollup.config.*, rspack*, simple-git-hooks*, stylelint*, tslint*, tsup.config.*, turbo*, typedoc*, unlighthouse*, vercel*, vetur.config.*, webpack*, workspace.json, xo.config.*, yarn*",
277 | "pubspec.yaml": ".metadata, .packages, all_lint_rules.yaml, analysis_options.yaml, build.yaml, pubspec.lock, pubspec_overrides.yaml",
278 | "pyproject.toml": ".pdm.toml, pdm.lock, pyproject.toml",
279 | "quasar.conf.js": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, playwright.config.*, postcss.config.*, puppeteer.config.*, quasar.extensions.json, rspack.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*",
280 | "readme*": "authors, backers*, changelog*, citation*, code_of_conduct*, codeowners, contributing*, contributors, copying, credits, governance.md, history.md, license*, maintainers, readme*, security.md, sponsors*",
281 | "remix.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, playwright.config.*, postcss.config.*, puppeteer.config.*, remix.*, rspack.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*",
282 | "rush.json": ".browserslist*, .circleci*, .commitlint*, .cz-config.js, .czrc, .dlint.json, .dprint.json, .editorconfig, .eslint*, .firebase*, .flowconfig, .github*, .gitlab*, .gitpod*, .huskyrc*, .jslint*, .lintstagedrc*, .markdownlint*, .node-version, .nodemon*, .npm*, .nvmrc, .pm2*, .pnp.*, .pnpm*, .prettier*, .releaserc*, .sentry*, .simple-git-hooks*, .stackblitz*, .styleci*, .stylelint*, .tazerc*, .textlint*, .tool-versions, .travis*, .versionrc*, .vscode*, .watchman*, .xo-config*, .yamllint*, .yarnrc*, Procfile, apollo.config.*, appveyor*, azure-pipelines*, bower.json, build.config.*, commitlint*, crowdin*, dangerfile*, dlint.json, dprint.json, eslint*, firebase.json, grunt*, gulp*, jenkins*, lerna*, lint-staged*, nest-cli.*, netlify*, nodemon*, npm-shrinkwrap.json, nx.*, package-lock.json, package.nls*.json, phpcs.xml, pm2.*, pnpm*, prettier*, pullapprove*, pyrightconfig.json, release-tasks.sh, release.config.*, renovate*, rollup.config.*, rspack*, simple-git-hooks*, stylelint*, tslint*, tsup.config.*, turbo*, typedoc*, unlighthouse*, vercel*, vetur.config.*, webpack*, workspace.json, xo.config.*, yarn*",
283 | "shims.d.ts": "*.d.ts",
284 | "svelte.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, houdini.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, mdsvex.config.js, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vite.config.*, vitest.config.*, webpack.config.*, windi.config.*",
285 | "vite.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*",
286 | "vue.config.*": "*.env, .babelrc*, .codecov, .cssnanorc*, .env.*, .envrc, .htmlnanorc*, .lighthouserc.*, .mocha*, .postcssrc*, .terserrc*, api-extractor.json, ava.config.*, babel.config.*, contentlayer.config.*, cssnano.config.*, cypress.*, env.d.ts, formkit.config.*, formulate.config.*, histoire.config.*, htmlnanorc.*, jasmine.*, jest.config.*, jsconfig.*, karma*, lighthouserc.*, playwright.config.*, postcss.config.*, puppeteer.config.*, rspack.config.*, svgo.config.*, tailwind.config.*, tsconfig.*, tsdoc.*, uno.config.*, unocss.config.*, vitest.config.*, webpack.config.*, windi.config.*"
287 | },
288 | "todohighlight.include": [
289 | "**/*.js",
290 | "**/*.jsx",
291 | "**/*.ts",
292 | "**/*.tsx",
293 | "**/*.html",
294 | "**/*.css",
295 | "**/*.scss",
296 | "**/*.vue"
297 | ],
298 | "todohighlight.keywords": [
299 | {
300 | "text": "TODO:",
301 | "backgroundColor": "#FCD34D"
302 | },
303 | {
304 | "text": "FIXME:",
305 | "backgroundColor": "#F87171"
306 | },
307 | {
308 | "text": "NOTE:",
309 | "backgroundColor": "#FEE2E2"
310 | },
311 | {
312 | "text": "HACK:",
313 | "backgroundColor": "#C7D2FE"
314 | },
315 | {
316 | "text": "REVIEW:",
317 | "backgroundColor": "#A7F3D0"
318 | }
319 | ],
320 | "todohighlight.defaultStyle": {
321 | "color": "#ffffff",
322 | "cursor": "pointer",
323 | "borderRadius": "2px"
324 | },
325 | "highlight-matching-tag.styles": {
326 | "opening": {
327 | "left": {
328 | "custom": {
329 | "borderWidth": "0 0 3px 0",
330 | "borderStyle": "solid",
331 | "borderColor": "#fca5a5",
332 | "borderRadius": "3px",
333 | "content": "''",
334 | "position": "absolute",
335 | "top": "0",
336 | "bottom": "0",
337 | "left": "0",
338 | "right": "0",
339 | "pointerEvents": "none",
340 | "zIndex": "-1",
341 | "animation": "highlight-matching-tag 1s ease-in-out infinite"
342 | }
343 | },
344 | "right": {
345 | "custom": {
346 | "borderWidth": "0 0 3px 0",
347 | "borderStyle": "solid",
348 | "borderColor": "#fca5a5",
349 | "borderRadius": "3px",
350 | "content": "''",
351 | "position": "absolute",
352 | "top": "0",
353 | "bottom": "0",
354 | "left": "0",
355 | "right": "0",
356 | "pointerEvents": "none",
357 | "zIndex": "-1",
358 | "animation": "highlight-matching-tag 1s ease-in-out infinite"
359 | }
360 | }
361 | }
362 | }
363 | }
364 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Welcome to fe-workflow 👋
2 |
3 | ## Introduce
4 |
5 | ### 📚 An operation guide for FE development engineers
6 |
7 |
8 |
9 | 
10 |
--------------------------------------------------------------------------------
/app.config.ts:
--------------------------------------------------------------------------------
1 | export default defineAppConfig({
2 | TITLE_EN: 'FE Workflow',
3 | TITLE_ZH: '前端工程化指南',
4 | DESCRIPTION_EN: 'design、build、specifications、develop、test、monitor、deploy、analyze、optimize',
5 | DESCRIPTION_ZH: '设计、搭建、规范、开发、测试、监控、部署、分析、优化',
6 | })
7 |
--------------------------------------------------------------------------------
/app.vue:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/assets/img/aside/design.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOUSANPANG/fe-workflow/c90807248b6b40ff70d35b28836b6c1d162ad41d/assets/img/aside/design.png
--------------------------------------------------------------------------------
/assets/img/aside/document.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOUSANPANG/fe-workflow/c90807248b6b40ff70d35b28836b6c1d162ad41d/assets/img/aside/document.png
--------------------------------------------------------------------------------
/assets/img/beam/docs_bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOUSANPANG/fe-workflow/c90807248b6b40ff70d35b28836b6c1d162ad41d/assets/img/beam/docs_bg.png
--------------------------------------------------------------------------------
/assets/img/beam/fill.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOUSANPANG/fe-workflow/c90807248b6b40ff70d35b28836b6c1d162ad41d/assets/img/beam/fill.jpg
--------------------------------------------------------------------------------
/assets/img/beam/home_bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOUSANPANG/fe-workflow/c90807248b6b40ff70d35b28836b6c1d162ad41d/assets/img/beam/home_bg.jpg
--------------------------------------------------------------------------------
/assets/img/beam/pink.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOUSANPANG/fe-workflow/c90807248b6b40ff70d35b28836b6c1d162ad41d/assets/img/beam/pink.jpg
--------------------------------------------------------------------------------
/assets/img/beam/sky.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOUSANPANG/fe-workflow/c90807248b6b40ff70d35b28836b6c1d162ad41d/assets/img/beam/sky.jpg
--------------------------------------------------------------------------------
/assets/style/base.css:
--------------------------------------------------------------------------------
1 | h1 {
2 | --at-apply: mt-8 tracking-tight text-3xl font-extrabold text-slate-900;
3 | }
4 | h2 {
5 | --at-apply: mb-2 tracking-normal whitespace-pre-wrap text-sm font-semibold text-sky-500;
6 | }
7 | h3 {
8 | --at-apply: mb-4 whitespace-pre-wrap text-xl font-semibold text-slate-900;
9 | }
10 | h4 {
11 | --at-apply: mb-4 whitespace-pre-wrap text-base text-slate-700;
12 | }
13 | p {
14 | --at-apply: mb-4 whitespace-pre-wrap text-base text-slate-700;
15 | }
16 |
17 | br {
18 | --at-apply: mt-1;
19 | }
20 | hr {
21 | --at-apply: my-8 border-t-2 border-slate-100;
22 | }
23 |
24 | pre {
25 | --at-apply: p-4 my-8 overflow-x-auto bg-slate-800 rounded-lg shadow-sm;
26 | }
27 | p > code,
28 | li > code {
29 | --at-apply: m-0 px-2 py-1 text-sm font-medium text-sky-500 bg-slate-900/20 rounded-md;
30 | }
31 |
32 | .doclink {
33 | @apply: !block !mt-1 !w-fit !text-slate-700 !font-semibold !underline !decoration-1 !underline-offset-4 !decoration-sky-500 !hover:text-sky-500;
34 | }
35 |
36 | ul,
37 | ol {
38 | @apply: !mt-2 !mb-4 !list-inside !text-slate-600;
39 | }
40 | ul {
41 | @apply: !list-disc;
42 | }
43 | li > ul {
44 | @apply: !mb-0 !py-0 !pb-2 !pl-8 !pr-4 !list-disc !text-slate-500;
45 | }
46 | ol {
47 | @apply: !mt-1 !list-decimal;
48 | }
49 |
50 | table {
51 | @apply: !mb-8 !text-sm !border-b !border-slate-400 !border-collapse;
52 | }
53 | thead {
54 | @apply: !bg-slate-50;
55 | }
56 | tr > th {
57 | @apply: !p-4 !text-left !border-b !border-slate-300 !text-slate-900 !font-semibold;
58 | }
59 | tr > td {
60 | @apply: !p-4 !border-b !border-slate-300 !text-slate-600;
61 | }
62 |
63 | ::-webkit-scrollbar {
64 | --at-apply: hidden;
65 | }
66 | ::-webkit-scrollbar-thumb {
67 | --at-apply: bg-slate-300 rounded-md;
68 | }
69 |
--------------------------------------------------------------------------------
/components/AppHeader.vue:
--------------------------------------------------------------------------------
1 |
45 |
46 |
47 |
127 |
128 |
--------------------------------------------------------------------------------
/components/content/Card.vue:
--------------------------------------------------------------------------------
1 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/components/content/Image.vue:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/components/content/Tabs.vue:
--------------------------------------------------------------------------------
1 |
8 |
9 |
10 |
11 |
12 |
25 | {{ item }}
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/components/navigation/NavigationAside.vue:
--------------------------------------------------------------------------------
1 |
19 |
20 |
21 |
22 |
23 |
24 |
32 |
37 | {{ item.title }}
41 |
42 |
43 |
44 |
45 |
46 |
{{ item.title }}
47 |
48 | {{ navItem.title }}
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/components/navigation/NavigationToc.vue:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 |
18 |
25 | {{ h2Item.text }}
26 |
27 |
34 | {{ h3Item.text }}
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/composables/useDevice.ts:
--------------------------------------------------------------------------------
1 | export const useUseDevice = () => {
2 | if (process.client) {
3 | const isMobile = ref(false)
4 | isMobile.value = /mobile/i.test(window.navigator.userAgent) || window.innerWidth <= 768
5 |
6 | return isMobile
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/composables/useFormatHash.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * @description 生成规范锚点链接
3 | * 1、解码链接
4 | * 2、去除首尾空格
5 | * 3、空格替换为'-'
6 | * 4、去除特殊字符
7 | * 5、小写
8 | * 6、如果首字符为数字,则在前面加上'_'
9 | */
10 | export const useFormatHash = (hashLink: string) => {
11 | const pattern = /[\!\@\#\$\%\^\&\*\(\)\+\{\[\}\]\|\:\;\"\'\<\,\>\.\?\`\~\~\·\!\@\#\¥\%\…\…\&\*\(\)\+\=\「\【\」\】\|\、\/\\\:\;\“\‘\《\,\》\。\?]/g;
12 | hashLink = hashLink
13 | .trim()
14 | .replace(/\s/g, '-')
15 | .replace(pattern, '')
16 | .replace(/--/g, '-')
17 | .toLowerCase();
18 |
19 | if (!isNaN(Number(hashLink[0]))) {
20 | hashLink = `_${hashLink}`
21 | }
22 |
23 | return `#${hashLink}`
24 | }
25 |
--------------------------------------------------------------------------------
/composables/useHeaderInfo.ts:
--------------------------------------------------------------------------------
1 | export const useHeaderInfo = () => {
2 | const repoGitHub = computed(() => {
3 | return {
4 | text: 'GitHub',
5 | icon: 'i-carbon-logo-github',
6 | link: 'https://github.com/LOUSANPANG/fe-workflow',
7 | target: '_blank'
8 | }
9 | })
10 |
11 | const headerLinks = computed(() => {
12 | return [
13 | {
14 | text: 'Docs',
15 | link: '/docs/documentation',
16 | target: '_self'
17 | },
18 | {
19 | text: 'Concept',
20 | link: '/concept/documentation',
21 | target: '_self'
22 | },
23 | {
24 | text: 'Blog',
25 | link: 'https://lousanpang.github.io',
26 | target: '_blank'
27 | }
28 | ]
29 | })
30 |
31 | return {
32 | repoGitHub,
33 | headerLinks,
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/composables/useLocale.ts:
--------------------------------------------------------------------------------
1 | export const useLocale = () => {
2 | return useState('locale', () => useDefaultLocale().value)
3 | }
4 |
5 | export const useDefaultLocale = (fallback = 'en-ZH') => {
6 | const locale = ref(fallback)
7 | if (process.server) {
8 | const reqLocale = useRequestHeaders()['accept-language']?.split(',')[0]
9 | if (reqLocale) {
10 | locale.value = reqLocale
11 | }
12 | } else if (process.client) {
13 | const navLang = navigator.language
14 | if (navLang) {
15 | locale.value = navLang
16 | }
17 | }
18 | return locale
19 | }
20 |
--------------------------------------------------------------------------------
/composables/useOrganizeAside.ts:
--------------------------------------------------------------------------------
1 | import type { NavItem } from '@nuxt/content/dist/runtime/types'
2 | import type { RouteType } from '~/types/navigation'
3 |
4 |
5 | export const useOrganizeAside = (navigation: Ref) => {
6 | const route = useRoute()
7 | const targetRoutName = ref('')
8 | if (route.fullPath.includes('docs')) {
9 | targetRoutName.value = 'docs'
10 | } else if (route.fullPath.includes('concept')) {
11 | targetRoutName.value = 'concept'
12 | }
13 |
14 | const routes: Array = navigation.value.filter((item) => (item.title.toLowerCase() === targetRoutName.value))
15 | const asideEarlyDev: RouteType[] = routes[0]?.children.filter((route: RouteType) => !route.children)
16 | const asideGuide: RouteType[] = routes[0]?.children.filter((route: RouteType) => route.children)
17 |
18 | return {
19 | asideEarlyDev,
20 | asideGuide
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/composables/useSetAppHead.ts:
--------------------------------------------------------------------------------
1 | export const useSetAppHead = () => {
2 | const { TITLE_EN, DESCRIPTION_EN } = useAppConfig()
3 |
4 | useHead({
5 | title: TITLE_EN,
6 | titleTemplate: title => title === TITLE_EN ? title : `${title} · ${TITLE_EN}`,
7 | meta: [
8 | { name: 'viewport', content: 'width=device-width, initial-scale=1' },
9 | { name: 'description', content: DESCRIPTION_EN },
10 | ],
11 | link: [
12 | {
13 | rel: 'icon', type: 'image/x-icon', href: `/favicon.ico`,
14 | },
15 | ],
16 | script: [
17 | {
18 | src: 'https://www.googletagmanager.com/gtag/js?id=G-L4BS2P1L41',
19 | async: true,
20 | },
21 | {
22 | innerHTML: `
23 | window.dataLayer = window.dataLayer || [];
24 | function gtag(){dataLayer.push(arguments);}
25 | gtag('js', new Date());
26 | gtag('config', 'G-L4BS2P1L41');
27 | `,
28 | type: 'text/javascript',
29 | }
30 | ]
31 | })
32 | }
33 |
--------------------------------------------------------------------------------
/composables/useToc.ts:
--------------------------------------------------------------------------------
1 | import type { linkType, tocType } from '~/types/navigation'
2 |
3 | export const useToc = (toc: tocType) => {
4 | const links: linkType[] = toc.links
5 |
6 | return links
7 | }
8 |
--------------------------------------------------------------------------------
/content/concept/10.documentation.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Documentation'
3 | description: '概念'
4 | navigation:
5 | icon: '/aside/document.png'
6 | title: 'Documentation'
7 | ---
8 |
9 | ## 令人难忘的知识概念
10 |
11 |
12 |
13 | 属性值计算过程、浏览器的渲染原理、事件循环机制、网络性能优化、工程化讨论...
14 |
--------------------------------------------------------------------------------
/content/concept/100.html/_dir.yml:
--------------------------------------------------------------------------------
1 | title: HTML
2 |
--------------------------------------------------------------------------------
/content/concept/200.css/1.attribute-calc.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: '属性值计算过程'
3 | ---
4 |
5 | ## 属性值计算过程
6 |
7 | ### `CSS无属性值`到`有属性值`
8 | - 确定声明值:合并作者该元素的样式表和浏览器默认样式
9 | - 层叠冲突
10 | - 比较重要性:作者样式表 > 浏览器默认样式表
11 | - 比较特殊性:权重(选择器)
12 | - 比较源次序:代码靠后的 > 代码靠前的
13 | - 使用继承:没有值得属性,若可以继承,继承父元素的值
14 | - 使用默认值:最终仍然没有值的,继承默认值
15 |
--------------------------------------------------------------------------------
/content/concept/200.css/_dir.yml:
--------------------------------------------------------------------------------
1 | title: CSS
2 |
--------------------------------------------------------------------------------
/content/concept/300.js/1.es5.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'ES5 基础'
3 | ---
4 |
5 | ## 非严格相等
6 |
7 | ### 两端类型一致
8 | - NaN 与 NaN 比较为 false
9 | - 除 NaN 外,两端类型一致时正常比较
10 |
11 | ```bash
12 | # 一种特殊情况 NaN
13 | console.log(NaN == NaN) # false
14 |
15 | # 除NaN外,两端类型一致时正常比较
16 | console.log(1 == 2) # false
17 | console.log('abc' == 'abc') # true
18 | console.log(null == null) # true
19 | console.log(undefined == undefined) # true
20 | console.log([] == []) # false
21 | ```
22 |
23 | ### 两端类型不一致
24 | - 一种特殊情况:null 和 undefined 比较
25 | - 两种规则:两端为原始类型转数字;两端一端为对象,**对象转原始**;
26 | ```bash
27 | # 一种特殊情况,null和undefined比较为true
28 | null == undefined # true
29 | null == 1 # false
30 |
31 | # 两种规则,两端为原始类型转数字
32 | 1 == '1' # true
33 | 1 == true # true
34 | false == '0' # true
35 |
36 | # 两种规则,两端一端为对象,对象转原始
37 | # 对象转原始类型分三步:
38 | # 1、查看对象有没有 [][Symbol.toPrimitive] 函数
39 | # 2、查看对象有没有 [].valueOf 函数
40 | # 3、调用对象的 [].toString 函数
41 | [] == 2 # false
42 | ['1'] == 1 # true
43 | ```
44 |
--------------------------------------------------------------------------------
/content/concept/300.js/2.prototype-chain.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: '原型链'
3 | ---
4 |
5 | ## 原型链全貌图
6 |
7 | ```js
8 | /**
9 | * 函数A产生对象a:new A() => a
10 | * 函数A本身自带原型对象:A.prototype
11 | * 对象a有个隐式原型指向函数A原型对象:a.__proto__ === A.prototype
12 | *
13 | * 函数A的原型对象 A.prototype => {} <= new Object()
14 | * 函数Object本子自带原型对象:Object.prototype
15 | * 函数A原型对象A.prototype有个隐式原型指向函数Object原型对象:A.prototype.__proto__ === Object.prototype
16 | * Object.prototype对象有个隐式原型指向null
17 | *
18 | * new Function => Object // typeof Object => 'function'
19 | * Object.__proto__ => Function.prototype
20 | * new Object => Function.prototype
21 | *
22 | * new Function => A
23 | * A.__proto__ => Function.prototype
24 | */
25 | ```
26 |
27 | ::Image{src="/content/concept/js_prototype_chain.png"}
28 | ::
29 |
--------------------------------------------------------------------------------
/content/concept/300.js/3.event-loop.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: '事件循环机制'
3 | ---
4 |
5 | ## 事件循环机制
6 |
7 | ### 原理
8 | js 是一门单线程语言,它运行在浏览器的渲染主线程中,而浏览器主线程只有一个。而主线程承担着诸多的工作,渲染页面、执行js等都在其中。
9 |
10 | 如果使用同步,极有可能导致主线程产生堵塞,从而导致消息队列中的其他任务无法得到执行。这样的话一方面导致繁忙的主线程白白的浪费时间,另一方面导致页面无法及时更新,给用户一种页面卡死的现象。
11 |
12 | 所以浏览器采用异步的方式来避免,具体做法是当某些任务发生时,比如计时器、网络、事件监听。主线程交给其他线程来处理,自身立即结束任务的执行,转而执行后续的代码。当其他线程完成时,将事先传递的回调函数包装成任务,加入到消息队列的末尾排队,等待主线程调度执行。
13 |
14 | 这种异步模式下,浏览器不会阻塞,从而最大限度的保证了单线程的流畅运行。
15 |
16 | ### 解释
17 | 事件循环又叫消息循环,是浏览器渲染主线程的工作方式。
18 |
19 | 在 Chrome 的源码中,它开启一个不会结束的 for 循环,每次循环从消息队列中取出第一个任务执行,而其他线程只需要在合适的时候将任务加入到队列末尾即可。
20 | 过去把消息队列简单分为宏队列和微队列,这种说法目前已无法满足复杂的浏览器环境,取而代之的是一种更加灵活多变的处理方式。
21 |
22 | 根据 W3C 官方的解释,每个任务有不同的类型,同类型的任务必须在同一个队列,不同的任务可以属于不同的队列。不同任务队列有不同的优先级,在一次事件循环中,由浏览器自行决定取哪一个队列的任务。
23 |
24 | 但浏览器必须有一个微队列,微队列的任务一定具有最高的优先级,必须优先调度执行。
25 | 渲染主线程 -> 微队列(promise) -> 交互队列(事件点击、浏览器滚动) -> 延时队列(定时器) -> ...队列
26 |
27 | ## js 中的计时器能做到精确计时吗?
28 | 1、计算机硬件没有原子钟,无法做到精确计时
29 | 2、操作系统的计时函数本身就有少量偏差,由于 js 的计时器最终调用的是操作系统的函数,也就携带了这些偏差
30 | 3、按照 W3C 的标准,浏览器实现计时器时,如果嵌套层级超过 5 层,并且有延时小于 4ms,那么延时会被设置为 4ms
31 | 4、受事件循环的影响,计时器的回调函数只能在主线程空闲时运行,因此又带来了偏差
32 |
--------------------------------------------------------------------------------
/content/concept/300.js/5.cjs-esm.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Commonjs和ESModule'
3 | ---
4 |
5 | ## Commonjs和ESModule区别
6 |
7 | ### Common js
8 |
9 | - 社区标准
10 | - 使用函数实现
11 | - 仅node环境支持
12 | - 动态依赖
13 | - 动态依赖同步执行
14 |
15 | ```js
16 | // require 函数原理
17 | /**
18 | * 一个模块(js文件)就是一个 {},隐形代表的是 module.exports
19 | * 在模块中直接打印 this,其实就是 module.exports
20 | * 不管是 this.xx exports.xx 其实都是往 module.exports 的对象挂载
21 | */
22 |
23 | function require(path) {
24 | // 第一步
25 | if (该模块有缓存) {
26 | return 缓存结果
27 | }
28 |
29 | function _run(exports, require, module, __filename, __dirname) {
30 | // js文件代码
31 | }
32 |
33 | // 第二步
34 | const module = {
35 | exports: {},
36 | }
37 |
38 | // 第三步
39 | _run.call(
40 | module.exports, // this 指向
41 | module.exports,
42 | require,
43 | module
44 | .模块路径,
45 | 模块所在目录,
46 | )
47 |
48 | // 第四步把 module.exports 加入到缓存中
49 |
50 | // 第五步
51 | return module.exports
52 | }
53 | ```
54 |
55 | ### ES Module
56 | - 官方标准
57 | - 使用新语法实现
58 | - 所有环境均支持
59 | - 静态依赖:在代码运行前就要确定依赖关系
60 | - 动态依赖是异步的
61 | - 符号绑定(引用地址传递)
62 |
63 |
64 |
65 | ## 经典题
66 |
67 | ### require 函数导出相关问题
68 |
69 | ```js
70 | // 1.js
71 | this.a = 1
72 | exports.b = 2
73 | module.exports.c = 3
74 |
75 | // 2.js
76 | const m = require('./1')
77 | console.log(m) // { a: 1, b: 2, c: 3 }
78 | ```
79 |
80 | ### ESModule 符号绑定相关问题
81 |
82 | ```js
83 | // a.js
84 | export var count = 0
85 | export function increase() {
86 | count ++
87 | }
88 |
89 | // b.js
90 | import { count, increase } from 'a.js';
91 | console.log(count) // 0
92 | increase()
93 | console.log(count) // 1
94 | ```
95 |
--------------------------------------------------------------------------------
/content/concept/300.js/7.design-pattern.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: '设计模式'
3 | ---
4 |
--------------------------------------------------------------------------------
/content/concept/300.js/_dir.yml:
--------------------------------------------------------------------------------
1 | title: JS
2 |
--------------------------------------------------------------------------------
/content/concept/400.browser/1.rendering-principle.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: '浏览器渲染原理'
3 | ---
4 |
5 | ## 浏览器是如何渲染页面
6 |
7 | ### 阐述
8 |
9 | 当浏览器的网络线程收到 HTML 文档后,会产生一个渲染任务,并将其传递给渲染主线程的消息队列。
10 | 在事件循环机制的作用下,渲染主线程取出消息队列中的渲染任务,开启渲染流程。
11 |
12 | 整个渲染流程分为多个阶段,分别是:HTML 解析、样式计算、布局、分层、绘制、分块、光栅化和合成。
13 | 每个阶段都有明确的输入和输出,上一个阶段的输出会成为下一个阶段的输入。
14 | 这样整个渲染流程就形成了一套组织严密的生产流水线。
15 |
16 | ### 渲染阶段
17 |
18 | HTML 解析 - Parse html
19 | - 解析过程中遇到 CSS 解析 CSS,遇到 JS 执行 JS。为了提高解析效率,浏览器在开始解析前,会启动一个预解析的线程,率先下载 HTML 中的外部 CSS 文件和外部的 JS 文件。
20 | - 如果主线程解析到 link 位置,此时外部的 css 文件还没有下载好,主线程不会等待,继续解析后续的 HTML。这是因为下载和解析 CSS 的工作是在预解析线程中进行的。这就是 CSS 不会阻塞 HTML 解析的根本原因。
21 | - 如果主线程解析到 script 位置,会停止解析 HTML,转而等待 JS 文件下载好,并将全局代码解析执行完成后,才能继续解析 HTML。这是因为 jS 代码的执行过程可能会修改当前的 DOM 树,所有 DOM 树的生成必须暂停。这就是 JS 会阻塞 HTML 解析的根本原因。
22 | - 完成后,会得到 DOM 树和 CSSOM 树,浏览器的默认样式、内部样式、行内样式均会包含在 CSSOM 树中。
23 |
24 | 样式计算
25 | - 主线程会遍历得到的 DOM 树,依次为树中的每个节点计算出它最终的样式,称之为 Computed Style。在这一过程中,很多预设值会变成绝对值,比如 red 会变成 rgb(255,0,0);相对单位会变成绝对单位,比如 em 会变成 px。
26 | - 完成后,会得到一颗带有样式的 DOM 树。
27 |
28 | 布局
29 | - 布局阶段会依次遍历 DOM 树的每一个节点,计算每个节点的几何信息。例如节点的宽高、相对包含块的位置。大部分时候,DOM 树和布局树并非一一对应。比如 dispaly:none 的节点没有几何信息,因此不会生成到布局树;又比如使用伪元素选择器,虽然 DOM 树中不存在这些伪元素节点,但他们拥有集合信息,所以会生成到布局树中。还有匿名行盒、匿名块盒等等都会导致 DOM 树和布局树无法一一对应。
30 | - 完成后,会得到布局树
31 |
32 | 分层
33 | 主线程会使用一套复杂的策略对整个布局树中进行分层。分层的好处在于,将来某一个层改变后,仅会对该层进行后续处理,从而提升效率。滚动条、堆叠上下文、transfrom、opacity等样式都会或多或少的影响分层结果,也可以通过 will-change 属性更大程度的影响分层结果。
34 |
35 | 绘制
36 | 主线程会为每个层单独产生绘制指令集,用于描述这一层的内容该如何画出来。完成绘制后,主线程将每个图层的绘制信息提交给合成线程,剩余工作将由合成线程完成。
37 |
38 | 分块
39 | 合成线程首先对每个图层进行分块,将其划分为更多的小区域。它会从线程池中拿取多个线程来完成分块工作。
40 |
41 | 光栅化
42 | 合成线程会将块信息交给 GPU 进程,以极高的速度完成光栅化。GPU 进程会开启多个线程来完成光栅化,并且优先处理靠近视口区域的块。光栅化的结果就是一块一块的位图。
43 |
44 | 画
45 | - 合成线程拿到每个层、每个块的位图后,生成一个个 指引 quad 信息。指引会标识出每个位图应该画到屏幕的哪个位置,以及会考虑到旋转、缩放等变形。变形发生在合成线程、与渲染中线程无关,这就是 transform 效率高的本质原因。
46 | - 合成线程会把 quad 提交给 GPU 进程,由 GPU 进程产生系统调用,提交给 GPU 硬件,完成最终的屏幕成像。
47 |
48 |
49 |
50 | ## 什么是 reflow
51 |
52 | - 重排,属于渲染阶段的布局阶段,本质是重新计算layout树、布局树。
53 | - 当进行了会影响布局树的操作后,需要重新计算布局树,会引发 layout。
54 | - 为了避免连续的多次操作导致布局树反复计算,浏览器会合并这些操作,当 js 代码全部完成后再进行统一计算。所以改动属性造成的 reflow 是异步完成的。
55 | - 也同样因为如此,当 js 获取布局属性时,就可能造成无法获取到最新的布局信息。浏览器在反复权衡下,最终决定获取属性立即 reflow。
56 |
57 |
58 |
59 | ## 什么是 repaint
60 |
61 | - 重绘,属于渲染阶段的绘制阶段,本质是重新根据分层信息计算了绘制指令。
62 | - 当改动了可见样式后,就需要重新计算,会引发 repaint。
63 | - 由于元素的布局信息也属于可见样式,所以 reflow 一定会引起 repaint。
64 |
65 |
66 |
67 | ## 为什么 transform 效率高
68 |
69 | - 因为 transform 既不会影响布局也不会影响绘制指令,它影响的只是渲染流程的最后一个 draw 阶段
70 | - 由于 draw 阶段在合成线程中,所以 transform 的变化几乎不会影响渲染主线程。反之渲染主线程无论如何忙碌,也不会影响 transform 的变化。
71 |
--------------------------------------------------------------------------------
/content/concept/400.browser/_dir.yml:
--------------------------------------------------------------------------------
1 | title: 浏览器
2 |
--------------------------------------------------------------------------------
/content/concept/500.network/_dir.yml:
--------------------------------------------------------------------------------
1 | title: 网络
2 |
--------------------------------------------------------------------------------
/content/concept/600.cli/_dir.yml:
--------------------------------------------------------------------------------
1 | title: 工程化
2 |
--------------------------------------------------------------------------------
/content/concept/700.project/_dir.yml:
--------------------------------------------------------------------------------
1 | title: 项目
2 |
--------------------------------------------------------------------------------
/content/docs/10.documentation.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Documentation'
3 | description: '介绍'
4 | navigation:
5 | icon: '/aside/document.png'
6 | title: 'Documentation'
7 | ---
8 |
9 | ## 前端工程化指南文档
10 |
11 |
12 |
13 | 针对UI设计适配、工程构建、目录规范、代码质量、提交约定、性能优化、代码测试、埋点监控、项目部署、数据分析等方面的前端工程化指南文档。
14 |
--------------------------------------------------------------------------------
/content/docs/100.standard-directory/1.fe-directory.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: '前端目录规范'
3 | ---
4 |
5 | ## 文件命名规范
6 |
7 | ### 项目名
8 |
9 | ```bash
10 | # kebab-case
11 | my-project-name
12 | ```
13 |
14 | ### 文件夹
15 |
16 | ```bash
17 | # kebab-case
18 | aa-bb/
19 | ```
20 |
21 | ### 公共组件
22 |
23 | ```bash
24 | # 始终 PascalCase,或始终使用 kebab-case。
25 | # 高级别的(一般化描述的) + 描述性的修饰词
26 | components/
27 | |- SearchButtonClear.vue
28 | |- SearchButtonRun.vue
29 | |- SearchInputQuery.vue
30 | |- SearchInputExcludeGlob.vue
31 | |- SettingsCheckboxTerms.vue
32 | |- SettingsCheckboxLaunchOnStartup.vue
33 | ```
34 |
35 | ### 静态文件
36 |
37 | ```bash
38 | # 图像文件
39 | img/
40 | |- banner_sina.gif
41 | |- logo_police.gif
42 |
43 | # HTML
44 | # 小写、优先使用单个单词
45 | # 多个单词使用 下划线
46 | |- success_report.html
47 |
48 | # CSS
49 | # 小写、优先使用单个单词、下划线开头
50 | # 多个单词使用 kebab-case
51 | assets/css/
52 | |- _color.scss
53 | |- xxx-ui.css
54 |
55 | # 源码脚本
56 | lib/
57 | |- aa_bb.ts
58 | ```
59 |
60 | ### 编译文件
61 |
62 | ```bash
63 | # 单文件组件
64 | |- hello-word.vue
65 |
66 | # 工具函数 JS
67 | # 小写、优先使用单个单词
68 | # 多个单词使用 kebab-case
69 | |- index.js
70 | |- date-util.js
71 | ```
72 |
73 |
74 |
75 | ## 特殊单词命名
76 |
77 | ### 单例组件名
78 |
79 | ```bash
80 | # 每个页面只使用一次
81 | # 不接受任何 prop
82 | # `The` 前缀命名
83 | components/
84 | |- TheHeading.vue
85 | |- TheSidebar.vue
86 | ```
87 |
88 | ### 基础组件名
89 |
90 | ```bash
91 | # 展示类的、无逻辑、无状态、不掺杂业务逻辑
92 | # 页面内可使用多次,不同页面也可复用,是高可复用组件
93 | # `Base` 前缀命名
94 | components/
95 | |- BaseButton.vue
96 | |- BaseTable.vue
97 | |- BaseIcon.vue
98 | ```
99 |
100 | ### 业务组件
101 |
102 | ```bash
103 | # 只在当前项目中会用到,不具有通用性
104 | # 掺杂了复杂业务的组件,拥有自身 data、prop 的相关处理
105 | # `Custom` 前缀命名
106 | components/
107 | |- CustomCard.vue
108 | ```
109 |
110 | ### 紧密耦合的组件名
111 |
112 | ```bash
113 | # 和父组件紧密耦合的子组件应该以父组件名作为前缀命名
114 | # `以父组件` 前缀命名
115 | components/
116 | |- TodoList.vue # 父组件
117 | |- TodoListItem.vue # 子组件
118 | |- TodoListItemButton.vue # 子组件
119 | ```
120 |
--------------------------------------------------------------------------------
/content/docs/100.standard-directory/3.linux-directory.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Linux目录规范'
3 | ---
4 |
5 | ### Linux 目录结构
6 |
7 | ```bash
8 | |- /opt # 第三方软件安装包
9 | |- java # java 安装包
10 | |- ...
11 | |- /usr # 用户软件
12 | |- local # 本地软件
13 | |- java # java软件
14 | |- /home # 用户目录
15 | |- /bin # 常用指令
16 | |- /boot # 启动文件
17 | |- /dev # 设备文件
18 | |- /etc # 配置文件
19 | |- /lib # 库文件
20 | |- /media # 可移动设备
21 | |- /mnt # 挂载目录
22 | |- /proc # 进程信息
23 | |- /root # root 用户目录
24 | |- /run # 运行时信息
25 | |- /sbin # 管理员常用指令
26 | |- /srv # 服务数据
27 | |- /sys # 系统信息
28 | |- /tmp # 临时文件
29 | |- /var # 日志
30 | |- /lost # 文件系统恢复
31 | ```
32 |
--------------------------------------------------------------------------------
/content/docs/100.standard-directory/_dir.yml:
--------------------------------------------------------------------------------
1 | title: 目录规范
2 |
--------------------------------------------------------------------------------
/content/docs/1000.standard-analyse/1.chrome.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: '性能优化分析'
3 | ---
4 |
5 | ## 速度性能检测工具
6 |
7 | [PageSpeed Insights 网站各项 RUM 数据](https://pagespeed.web.dev/?utm_source=psi&utm_medium=redirect){.doclink}
8 | [WebPageTest 网站速度测试](https://www.webpagetest.org/){.doclink}
9 |
--------------------------------------------------------------------------------
/content/docs/1000.standard-analyse/2.user-traffic.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: '用户数据分析'
3 | ---
4 |
5 | ## 参考链接
6 | [友盟](https://www.umeng.com/){.doclink}
7 | [google analytics](https://analytics.google.com/){.doclink}
8 | [Umami](https://github.com/umami-software/umami){.doclink}
9 |
--------------------------------------------------------------------------------
/content/docs/1000.standard-analyse/_dir.yml:
--------------------------------------------------------------------------------
1 | title: 数据分析
2 |
--------------------------------------------------------------------------------
/content/docs/20.design.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Design'
3 | description: '设计响应适配'
4 | navigation:
5 | icon: '/aside/design.png'
6 | title: 'Design'
7 | ---
8 |
9 | ## 响应适配
10 |
11 | ### 早期方案:UI设计宽度为980px
12 | ```html
13 |
18 |
19 | ```
20 |
21 | ### 过渡方案:viewport 缩放比
22 |
23 | ```js
24 | // 动态设置 viewport 缩放比
25 | (function (designWidth) {
26 | const dEl = document.documentElement
27 | let meta = document.querySelector('meta[name=viewport]')
28 |
29 | if (!meta) {
30 | meta = document.createElement('meta')
31 | meta.setAttribute('name', 'viewport')
32 | document.head.appendChild(meta)
33 | }
34 |
35 | function setMetaContent() {
36 | const deviceWidth = dEl.clientWidth
37 | const scale = deviceWidth / designWidth
38 | const content = `width=${deviceWidth}, initial-scale=${scale}`
39 | meta.setAttribute('content', content)
40 | }
41 | setMetaContent()
42 |
43 | window.addEventListener('resize', setMetaContent)
44 | })(750)
45 | ```
46 |
47 | ### 过渡方案:flexible + rem
48 |
49 | [lib-flexible 动态设置根字体](https://github.com/amfe/lib-flexible){.doclink}
50 | [postcss-pxtorem px转rem](https://github.com/cuth/postcss-pxtorem){.doclink}
51 |
52 | ::tabs
53 | ---
54 | tabs: ['bash', 'index.html', 'postcss.config.js', 'main.js']
55 | ---
56 |
57 | #bash
58 | ```bash
59 | pnpm add amfe-flexible
60 | pnpm add -D postcss postcss-pxtorem
61 | ```
62 |
63 | #index.html
64 | ```html
65 |
66 | ```
67 |
68 | #postcss.config.js
69 | ```js
70 | module.exports = {
71 | plugins: {
72 | 'postcss-pxtorem': {
73 | // 设计稿的 1/10,750 -> 75 375 -> 37.5
74 | rootValue: 37.5,
75 | // 需要被转换的属性
76 | propList: ['*'],
77 | // 不进行px转换的选择器
78 | selectorBlackList: [],
79 | },
80 | },
81 | }
82 | ```
83 |
84 | #main.js
85 | ```js
86 | import 'amfe-flexible/index.js'
87 | ```
88 | ::
89 |
90 | ### 方案:autofit.js 自适应工具
91 |
92 | [autofit.js 自适应工具](https://github.com/LarryZhu-dev/autofit.js){.doclink}
93 |
94 |
95 | ### 方案:px转vw
96 |
97 | [postcss-px-to-viewport px转vw](https://github.com/evrone/postcss-px-to-viewport){.doclink}
98 | [vw 兼容方案](https://github.com/rodneyrehm/viewport-units-buggyfill?spm=ata.13261165.0.0.5c016ef2PzyaPL){.doclink}
99 |
100 |
101 | ### 方案:Tailwind CSS ⭐️
102 |
103 | [Tailwind CSS](https://tailwindcss.com/){.doclink}
104 | [Responsive Design](https://tailwindcss.com/docs/responsive-design){.doclink}
105 |
106 |
107 | ### 方案:UnoCSS ⭐️
108 |
109 | [UnoCSS](https://unocss.dev/){.doclink}
110 | [theme breakpoints](https://unocss.dev/config/theme#breakpoints){.doclink}
111 |
112 |
113 |
114 | ## 特殊场景情况
115 |
116 | ### 场景一:适配 Retina 屏
117 |
118 | ::tabs
119 | ---
120 | tabs: ['html', 'css']
121 | ---
122 |
123 | #html
124 | ```html
125 |
129 | ```
130 |
131 | #css
132 | ```css
133 | /* 关于图片 */
134 | [data-dpr="1"] .logo {
135 | background-image: url(image@1x.jpg);
136 | }
137 | [data-dpr="2"] .logo {
138 | background-image: url(image@2x.jpg);
139 | }
140 | [data-dpr="3"] .logo {
141 | background-image: url(image@3x.jpg);
142 | }
143 | /* 1px 的问题 */
144 | .u-border {
145 | position: relative;
146 | &::after {
147 | content: "";
148 | position: absolute;
149 | bottom: 0px;
150 | left: 0px;
151 | right: 0px;
152 | border-top: 1px solid #666;
153 | transform: scaleY(0.5);
154 | }
155 | }
156 | ```
157 |
158 | ::
159 |
160 | ### 场景二:适配图片不失真
161 |
162 | ```html
163 |
174 |
183 |
184 |
189 |
204 | ```
205 |
206 | ### 场景三:适配 iPhoneX 安全区域
207 |
208 | ::tabs
209 | ---
210 | tabs: ['html', 'css']
211 | ---
212 |
213 | #html
214 | ```html
215 |
216 |
217 | ```
218 |
219 | #css
220 | ```css
221 | /* fixed 完全吸底元素场景的适配 */
222 | /* 通过加内边距 padding 扩展高度 */
223 | .container {
224 | padding-bottom: constant(safe-area-inset-bottom);
225 | padding-bottom: env(safe-area-inset-bottom);
226 | }
227 | /* fixed 非完全吸底元素场景的适配 */
228 | .container {
229 | margin-bottom: constant(safe-area-inset-bottom);
230 | margin-bottom: env(safe-area-inset-bottom);
231 | }
232 | ```
233 | ::
234 |
235 |
236 |
237 | ## 主题切换方案
238 |
239 | ### 方案一:CSS变量 + 类名切换
240 |
241 | ::tabs
242 | ---
243 | tabs: ['js', 'css']
244 | ---
245 |
246 | #js
247 | ```js
248 | // 更改根目录类名
249 | function changeTheme(theme) {
250 | document.body.className = theme
251 | }
252 | ```
253 |
254 | #css
255 | ```css
256 | /* 定义根作用域下默认变量 */
257 | :root {
258 | --theme-color: #333;
259 | --theme-background: #eee;
260 | }
261 | /* 暗夜模式下变量 */
262 | .dark {
263 | --theme-color: #eee;
264 | --theme-background: #333;
265 | }
266 |
267 | .container {
268 | color: var(--theme-color);
269 | background: var(--theme-background);
270 | }
271 | ```
272 | ::
273 |
274 | ### 方案二:v-bind
275 |
276 | ```vue
277 |
282 |
283 |
284 |
285 |
286 |
287 |
292 | ```
293 |
294 | ### 方案三:SCSS变量 + 类名切换
295 |
296 | ::tabs
297 | ---
298 | tabs: ['theme-default.scss', 'theme-red.scss', 'index.scss', 'js']
299 | ---
300 |
301 | #theme-default.scss
302 | ```css
303 | [data-theme=default] {
304 | --color-primary: #516BD9;
305 | }
306 | ```
307 |
308 | #theme-red.scss
309 | ```css
310 | [data-theme=red] {
311 | --color-primary: #DF291E;
312 | }
313 | ```
314 |
315 | #index.scss
316 | ```css
317 | $--color-primary: var(--color-primary) !default;
318 | ```
319 |
320 | #js
321 | ```js
322 | document.documentElement.setAttribute('data-theme', 'default')
323 | ```
324 | ::
325 |
326 | ### 方案四:CSS变量 + 动态setProperty
327 |
328 | ::tabs
329 | ---
330 | tabs: ['css', 'js']
331 | ---
332 |
333 | #css
334 | ```css
335 | /* 全局中设置好预设的全局CSS变量样式 */
336 | :root {
337 | --theme-color: #333;
338 | --theme-background: #eee;
339 | }
340 | ```
341 |
342 | #js
343 | ```js
344 | /**
345 | * attr 预设变量属性 eg. --theme-color --theme-background ...
346 | * val 设置的值 eg. #fff 100px ...
347 | */
348 | function setCssVar(attr, val, dom = document.documentElement) {
349 | dom.style.setProperty(prop, val)
350 | }
351 | // 调用函数修改指定的CSS变量值
352 | setCssVar('--theme-color', '#fff')
353 | ```
354 | ::
355 |
356 | ### 方案五:filter
357 |
358 | ```css
359 | body {
360 | /* 改变整体色调 */
361 | filter: hue-rotate(45deg);
362 | /* 悼念色 */
363 | /* filter: grayscale(1); */
364 | }
365 | ```
366 |
367 |
368 |
369 | ## ICON
370 |
371 | ### 方案一:Iconfont
372 |
373 | [Iconfont](https://www.iconfont.cn/){.doclink}
374 | [Web 端使用](https://www.iconfont.cn/help/detail?spm=a313x.help_detail.i1.d8d11a391.24b33a81WeTzjy&helptype=code){.doclink}
375 |
376 |
377 | ### 方案二:UnoCSS Icons ⭐️
378 |
379 | [UnoCSS Icons](https://unocss.dev/presets/icons){.doclink}
380 | [all available icons](https://icones.js.org/){.doclink}
381 |
382 |
383 |
384 | ## 参考
385 |
386 | ### 设计工具
387 |
388 | [Figma](https://www.figma.com/){.doclink}
389 | [摹客](https://www.mockplus.cn/){.doclink}
390 | [Sketch](https://www.sketch.com/){.doclink}
391 |
392 |
393 | ### 屏幕尺寸
394 |
395 | [尺寸直观图](https://screensizemap.com/){.doclink}
396 | [尺寸参数大全](https://uiiiuiii.com/screen/index.htm){.doclink}
397 | [纸张尺寸转换](https://www.papersizes.org/a-paper-sizes.htm){.doclink}
398 |
399 |
400 | ### 设计规范
401 |
402 | [超人的电话亭UI设计师知识库](https://weeks-fix-dzb.craft.me/QtMOVu7kcubeUf){.doclink}
403 |
404 |
405 | ### 设计资源及灵感
406 |
407 | [cbc.design](https://uxchi.notion.site/Hey-I-m-Chi-8e9115aa3de44ae0857d402ace47d076){.doclink}
408 | [优设](https://hao.uisdc.com/){.doclink}
409 | [saaspo](https://www.saaspo.com/){.doclink}
410 | [refto](https://refto.one/){.doclink}
411 | [MFSC123.COM](https://www.mfsc123.com/){.doclink}
412 |
413 |
--------------------------------------------------------------------------------
/content/docs/200.standard-code/.5.tsconfig.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'tsconfig'
3 | description: 'TypeScript配置指南'
4 | ---
5 |
--------------------------------------------------------------------------------
/content/docs/200.standard-code/1.vscode.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'vscode'
3 | description: 'vscode配置及拓展'
4 | ---
5 |
6 | ## vscode
7 |
8 | ### settings and extensions
9 |
10 | [LOUSANPANG's VS Code Settings](https://github.com/LOUSANPANG/vscode-settings){.doclink}
11 | [Anthony's VS Code Settings](https://github.com/antfu/vscode-settings){.doclink}
12 |
13 | ```bash
14 | .vscode/
15 | |- extensions.json # 插件
16 | |- setting.json # 配置
17 | |- global.code-snippets # 代码片段
18 | .editorconfig # 跨编辑器代码配置
19 | ```
20 |
21 |
22 |
23 | ## .editorconfig
24 |
25 | [EditorConfig](http://EditorConfig.org){.doclink}
26 |
27 | ```bash
28 | # EditorConfig is awesome: http://EditorConfig.org
29 |
30 | # top-most EditorConfig file
31 | root = true
32 |
33 | [*.md]
34 | insert_final_newline = false
35 | trim_trailing_whitespace = false
36 |
37 | # Unix-style newlines with a newline ending every file
38 | [*]
39 | charset = utf-8
40 | indent_style = space
41 | indent_size = 2
42 | trim_trailing_whitespace = true # 去除行首的任意空白字符
43 | end_of_line = lf # 控制换行类型(lf | cr | crlf)
44 | insert_final_newline = true # 始终在文件末尾插入一个新行
45 | max_line_length = 100
46 | ```
47 |
--------------------------------------------------------------------------------
/content/docs/200.standard-code/2.eslint.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'ESlint'
3 | description: 'ESlint配置使用指南'
4 | ---
5 |
6 | ## 他人配置方案
7 |
8 | ### 方案一:@antfu/eslint-config
9 |
10 | [Anthony's ESLint config](https://github.com/antfu/eslint-config){.doclink}
11 |
12 |
13 |
14 | ## 手动配置方案
15 |
16 | ::tabs
17 | ---
18 | tabs: [ 'bash', 'package.json', 'eslint.config.js', 'vscode' ]
19 | ---
20 |
21 | #bash
22 | ```bash
23 | pnpm add -D eslint
24 |
25 | npx eslint --init
26 | ```
27 |
28 | #package.json
29 | ```json
30 | {
31 | "scripts": {
32 | "lint": "npx eslint --ext .js,.jsx,.ts,.tsx src",
33 | "lint-fix": "npx eslint --fix --ext .js,.jsx,.ts,.tsx src"
34 | }
35 | }
36 | ```
37 |
38 | #eslint.config.js
39 | ```js
40 | // https://eslint.org/docs/latest/use/configure/
41 | module.exports = {
42 | root: true,
43 | env: {},
44 | globals: {},
45 | parser: '',
46 | parserOptions: {
47 | ecmaFeatures: {
48 | jsx: true,
49 | },
50 | },
51 | plugins: [],
52 | extends: [],
53 | rules: {
54 | 'semi': 'off',
55 | 'comma-dangle': 'off',
56 | 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
57 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
58 | },
59 | ignores: ['dist', 'node_modules'],
60 | }
61 | ```
62 |
63 | #vscode
64 | ```json
65 | // 添加 vscode ESLint 插件
66 | // "dbaeumer.vscode-eslint"
67 |
68 | // 配置setting.json
69 | {
70 | "editor.formatOnSave": true,
71 | "editor.codeActionsOnSave": {
72 | "source.fixAll.eslint": true
73 | }
74 | }
75 | ```
76 |
77 | ::
78 |
--------------------------------------------------------------------------------
/content/docs/200.standard-code/3.prettier.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Prettier'
3 | description: 'Prettier配置使用指南'
4 | ---
5 |
6 | ## 手动配置方案
7 |
8 | [prettier](https://prettier.io/){.doclink}
9 |
10 | ::tabs
11 | ---
12 | tabs: [ 'bash', 'eslintrc', 'prettierrc', 'vscode' ]
13 | ---
14 |
15 | #bash
16 | ```bash
17 | pnpm add -D prettier
18 |
19 | # eslint-config-prettier 禁用掉所有和 prettier 冲突的规则
20 | pnpm add -D eslint-config-prettier
21 |
22 | # eslint-plugin-prettier 以符合 eslint 规则的方式格式化代码并提示对应的修改建议
23 | pnpm add -D eslint-plugin-prettier
24 | ```
25 |
26 | #eslintrc
27 | ```json
28 | // .eslintrc
29 | {
30 | "extends": ["plugin:prettier/recommended"]
31 | }
32 | ```
33 |
34 | #prettierrc
35 | ```json
36 | {
37 | "bracketSpacing": true,
38 | "semi": false,
39 | "tabWidth": 2,
40 | "proseWrap": "never",
41 | "endOfLine": "auto",
42 | "printWidth": 100,
43 | "singleQuote": true,
44 | "trailingComma": "none",
45 | "vueIndentScriptAndStyle": true,
46 | "htmlWhitespaceSensitivity": "strict"
47 | }
48 | ```
49 |
50 | #vscode
51 | ```bash
52 | # 添加 Prettier 插件
53 | # esbenp.prettier-vscode
54 | ```
55 |
56 | ::
57 |
--------------------------------------------------------------------------------
/content/docs/200.standard-code/4.stylelint.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Stylelint'
3 | description:
4 | ---
5 |
6 | ## 手动配置方案
7 |
8 | [Stylelint](https://stylelint.io/){.doclink}
9 |
10 | ::tabs
11 | ---
12 | tabs: [ 'bash', 'stylelintrc', 'package.json', 'vscode' ]
13 | ---
14 |
15 | #bash
16 | ```bash
17 | # stylelint-config-standard 标准配置
18 | pnpm add stylelint stylelint-config-standard -D
19 |
20 | # 【可选】排序扩展
21 | pnpm add stylelint-order -D
22 | # 【可选】规范的排序扩展
23 | pnpm add stylelint-config-rational-order -D
24 |
25 | # 【可选】支持校验scss语法的插件
26 | pnpm add stylelint-scss -D
27 | ```
28 |
29 | #stylelintrc
30 | ```json
31 | {
32 | "extends": [
33 | "stylelint-config-standard",
34 | "stylelint-config-rational-order" // 可选
35 | ],
36 | "plugins": [
37 | "stylelint-scss" // 可选
38 | ],
39 | "rules": {
40 | // stylelint-config-rational-order 规则
41 | // 1.Positioning 位置属性
42 | // 2.Box Model 盒子属性
43 | // 3.Typography 文字属性
44 | // 4.Visual 视觉属性
45 | // 5.Animation Misc 其他
46 |
47 | // 与 prettier 规则冲突
48 | "declaration-block-trailing-semicolon": null
49 | },
50 | "ignoreFiles": ["build", "dist", "node_modules"]
51 | }
52 | ```
53 |
54 | #package.json
55 | ```json
56 | {
57 | "scripts": {
58 | "lint:style": "stylelint {components,src}**/*.{vue,html,css,sss,less,scss,sass}",
59 | "fix:style": "stylelint {components,src}**/*.{vue,html,css,sss,less,scss,sass} --fix"
60 | }
61 | }
62 | ```
63 |
64 | #vscode
65 | ```json
66 | // 添加 stylelint 插件
67 | // stylelint.vscode-stylelint
68 |
69 | // 配置 setting.json 自动格式化
70 | {
71 | "editor.formatOnSave": true,
72 | "editor.codeActionsOnSave": {
73 | "source.fixAll.stylelint": true
74 | }
75 | }
76 | ```
77 |
78 | ::
79 |
--------------------------------------------------------------------------------
/content/docs/200.standard-code/_dir.yml:
--------------------------------------------------------------------------------
1 | title: 编码规范
2 |
--------------------------------------------------------------------------------
/content/docs/2000.toolbox/1.mac.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Mac 工具箱'
3 | ---
4 |
5 | ## 工程师 Mac 工具箱
6 |
7 | ### 网络安全
8 |
9 | [魔戒(科学上网工具)](https://mojie.app/dashboard){.doclink}
10 | [西游(科学上网工具)](https://sunwk.fun/i/){.doclink}
11 | [1Password(密码管理工具)](https://1password.com/){.doclink}
12 |
13 | ### 开发
14 |
15 | [Warp(终端)](https://www.warp.dev/){.doclink}
16 | [Homebrew(命令行包管理器工具)](https://brew.sh/){.doclink}
17 | [Oh My Zsh(命令行工具)](https://ohmyz.sh/){.doclink}
18 | [Git](https://git-scm.com/){.doclink}
19 | [Node.js](https://nodejs.org/){.doclink}
20 | [nvm(Node.js 版本管理工具)](https://github.com/nvm-sh/nvm){.doclink}
21 | [volta(代替 nvm 的node版本管理工具)](https://github.com/volta-cli/volta){.doclink}
22 | [Navicat(数据库管理工具)](https://www.navicat.com.cn/){.doclink}
23 | [Termius(SSH工具)](https://termius.com/){.doclink}
24 | [VSCode](https://code.visualstudio.com/){.doclink}
25 | [IDEA](https://www.jetbrains.com/idea/){.doclink}
26 | [HBuilderX](https://www.dcloud.io/hbuilderx.html){.doclink}
27 | [Charles(抓包工具)](https://www.charlesproxy.com/){.doclink}
28 |
29 | ### 生产力
30 |
31 | [Chrome](https://www.google.com/chrome/){.doclink}
32 | [Bob(翻译工具)](https://github.com/ripperhe/Bob){.doclink}
33 | [snipaste](https://zh.snipaste.com/){.doclink}
34 |
35 | ### 设计
36 |
37 | [Sketch(设计工具)](https://www.sketch.com/){.doclink}
38 | [Figma(设计工具)](https://www.figma.com/){.doclink}
39 | [Adobe(Adobe全家桶)](https://www.superso.top/Adobe/){.doclink}
40 |
41 | ### 影像相关
42 |
43 | [Downie(视频下载工具)](https://software.charliemonroe.net/downie/){.doclink}
44 | [IINA(视频播放器)](https://iina.io/){.doclink}
45 | [Kap(屏幕录制工具)](https://getkap.co/){.doclink}
46 |
47 | ### 生活
48 |
49 | [同花顺](https://www.10jqka.com.cn/){.doclink}
50 |
51 | ## 参考链接
52 |
53 | [终极一站式教程](https://44maker.github.io/wiki/Mac/index.html){.doclink}
54 |
--------------------------------------------------------------------------------
/content/docs/2000.toolbox/2.windows.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'windows 工具箱'
3 | ---
4 |
5 | ## 工程师 Windows 工具箱
6 |
7 | ### 网络安全
8 |
9 | [魔戒(科学上网工具)](https://mojie.app/dashboard){.doclink}
10 | [西游(科学上网工具)](https://sunwk.fun/i/){.doclink}
11 |
12 | ### 开发
13 |
14 | [Oh My Zsh](https://ohmyz.sh/){.doclink}
15 | [Git](https://git-scm.com/){.doclink}
16 | [Node.js](https://nodejs.org/){.doclink}
17 | [nvm(Node.js 版本管理工具)](https://github.com/nvm-sh/nvm){.doclink}
18 | [Navicat(数据库管理工具)](https://www.navicat.com.cn/){.doclink}
19 | [XShell(SSH工具)](https://www.xshell.com/zh/xshell/){.doclink}
20 | [XFtp(网络传输文件)](https://www.xshell.com/zh/xftp/){.doclink}
21 | [Redis Desktop Manager(Redis 可视化管理工具)](https://github.com/uglide/RedisDesktopManager){.doclink}
22 | [VSCode](https://code.visualstudio.com/){.doclink}
23 | [IDEA](https://www.jetbrains.com/idea/){.doclink}
24 | [HBuilderX](https://www.dcloud.io/hbuilderx.html){.doclink}
25 | [Charles(抓包工具)](https://www.charlesproxy.com/){.doclink}
26 |
27 | ### 生产力
28 |
29 | [Chrome](https://www.google.com/chrome/){.doclink}
30 | [snipaste](https://zh.snipaste.com/){.doclink}
31 |
32 | ### 设计
33 |
34 | [Sketch(设计工具)](https://www.sketch.com/){.doclink}
35 | [Figma(设计工具)](https://www.figma.com/){.doclink}
36 | [Adobe(Adobe全家桶)](https://www.superso.top/Adobe/){.doclink}
37 |
38 | ### 生活
39 |
40 | [同花顺](https://www.10jqka.com.cn/){.doclink}
41 |
--------------------------------------------------------------------------------
/content/docs/2000.toolbox/3.tv.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'tv 工具箱'
3 | ---
4 |
5 | ## 工程师 Tv 工具箱
6 |
7 | ### 网络安全
8 |
9 | [魔戒(科学上网工具)](https://mojie.app/dashboard){.doclink}
10 | [西游(科学上网工具)](https://sunwk.fun/i/){.doclink}
11 |
12 | ### 影像相关
13 |
14 | [一席(演讲类)](https://yixi.tv/#/home){.doclink}
15 | [netflix()](https://www.netflix.com/){.doclink}
16 |
17 | ### 电视直播
18 |
19 | [IPTV](https://iptv-org.github.io/iptv/index.m3u){.doclink}
20 | [my-tv](https://github.com/lizongying/my-tv){.doclink}
21 |
--------------------------------------------------------------------------------
/content/docs/2000.toolbox/_dir.yml:
--------------------------------------------------------------------------------
1 | title: 软件工具箱
2 |
--------------------------------------------------------------------------------
/content/docs/300.standard-commit/1.husky-lintstaged.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'husky&lintstaged'
3 | ---
4 |
5 | ## Husky、lint-staged
6 |
7 | ::tabs
8 | ---
9 | tabs: [ 'bash', 'package.json', 'husky' ]
10 | ---
11 |
12 | #bash
13 | ```bash
14 | pnpm add -D husky lint-staged
15 |
16 | pnpm exec husky init
17 |
18 | echo "npx lint-staged" > .husky/pre-commit
19 | ```
20 |
21 | #package.json
22 | ```json
23 | {
24 | "scripts": {
25 | "prepare": "husky"
26 | },
27 | "lint-staged": {
28 | "*": "eslint --fix"
29 | }
30 | }
31 | ```
32 |
33 | #husky
34 | ```bash
35 | # .husky/pre-commit
36 | npx lint-staged
37 | ```
38 |
39 | ::
40 |
41 |
42 |
43 | ## 参考链接
44 |
45 | [Husky](https://github.com/typicode/husky){.doclink}
46 |
47 | [lint-staged](https://github.com/lint-staged/lint-staged){.doclink}
48 |
49 | [simple-git-hooks](https://github.com/toplenboren/simple-git-hooks){.doclink}
50 |
--------------------------------------------------------------------------------
/content/docs/300.standard-commit/2.commitizen-commitlint.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'commitizen&commitlint'
3 | ---
4 |
5 | ## 检测commit备注规范
6 |
7 | ### commitlint
8 |
9 | ::tabs
10 | ---
11 | tabs: [ 'bash', 'commitlint.config.js', 'husky' ]
12 | ---
13 |
14 | #bash
15 | ```bash
16 | # lint commit messages
17 | pnpm add @commitlint/cli -D
18 |
19 | # 一份符合 Angular 团队规范校验的配置
20 | pnpm add @commitlint/config-conventional -D
21 |
22 | # 配置husky监听commit-msg
23 | npx husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"'
24 | ```
25 |
26 | #commitlint.config.js
27 | ```js
28 | // commitlint.config.js
29 | module.exports = {
30 | extends: ['@commitlint/config-conventional'],
31 | rules: {
32 | 'type-enum': [
33 | 2,
34 | 'always',
35 | [
36 | 'feat', // 新功能 feature
37 | 'fix', // 修复 bug
38 | 'docs', // 文档注释
39 | 'style', // 代码格式(不影响代码运行的变动)
40 | 'refactor', // 重构(既不增加新功能,也不是修复bug)
41 | 'perf', // 性能优化
42 | 'test', // 增加测试
43 | 'chore', // 构建过程或辅助工具的变动
44 | 'revert', // 回退
45 | 'build', // 打包
46 | ],
47 | ],
48 | // subject 大小写不做校验
49 | 'subject-case': [0],
50 | },
51 | }
52 | ```
53 |
54 | #husky
55 | ```bash
56 | # .husky/commit-msg
57 | npx --no-install commitlint --edit "$1"
58 | ```
59 | ::
60 |
61 |
62 |
63 | ## 添加commit辅助备注信息
64 |
65 | ### commitizen
66 |
67 | ::tabs
68 | ---
69 | tabs: [ 'bash', 'package.json', 'cz-config.js' ]
70 | ---
71 |
72 | #bash
73 | ```bash
74 | # git cz 替代 git commit,生成符合规范的 commit message。
75 | pnpm add -D commitizen
76 |
77 | # 指定一套符合自己团队的规范代替 Angular 规范
78 | pnpm add -D cz-customizable
79 | ```
80 |
81 | #package.json
82 | ```json
83 | {
84 | "config": {
85 | "commitizen": {
86 | "path": "node_modules/cz-customizable"
87 | }
88 | }
89 | }
90 | ```
91 |
92 | #cz-config.js
93 | ```js
94 | // .cz-config.js
95 | 'use strict'
96 | module.exports = {
97 | messages: {
98 | type: '选择你要提交的类型:',
99 | scope: '选择一个提交范围(可选):',
100 | customScope: '请输入自定义的提交范围(可选):',
101 | subject: '填写简短精炼的变更描述:\n',
102 | // body: '填写更加详细的变更描述(可选)。使用 "|" 换行:\n',
103 | // breaking: '列举非兼容性重大的变更(可选)。使用 "|" 换行:\n',
104 | // footerPrefixsSelect: '选择关联issue前缀(可选):',
105 | // customFooterPrefixs: '输入自定义issue前缀:',
106 | // footer: '列举关联issue (可选) 例如: #31, #I3244:\n',
107 | confirmCommit: '是否提交或修改commit?',
108 | },
109 |
110 | types: [
111 | { value: 'feat', name: 'feat: 新增功能' },
112 | { value: 'fix', name: 'fix: 修复 bug' },
113 | { value: 'docs', name: 'docs: 文档变更' },
114 | { value: 'style', name: 'style: 代码格式(不影响功能,例如空格、分号等格式修正)' },
115 | { value: 'refactor', name: 'refactor: 代码重构(不包括 bug 修复、功能新增)' },
116 | { value: 'perf', name: 'perf: 性能优化' },
117 | { value: 'test', name: 'test: 添加、修改测试用例' },
118 | { value: ' build', name: 'build: 构建流程、外部依赖变更(如升级 npm 包、修改 webpack 配置等)' },
119 | { value: 'ci', name: 'ci: 修改 CI 配置、脚本' },
120 | { value: 'chore', name: 'chore: 对构建过程或辅助工具和库的更改(不影响源文件、测试用例)' },
121 | { value: 'revert', name: 'revert: 回滚 commit' },
122 | ],
123 |
124 | scopes: [
125 | ['view', '页面相关'],
126 | ['components', '组件相关'],
127 | ['utils', 'utils 相关'],
128 | ['styles', '样式相关'],
129 | ['deps', '项目依赖'],
130 | ['workflows', '部署相关'],
131 | ['md', '文档相关'],
132 | ['other', '其他修改'],
133 | ['custom', '以上都不是?我要自定义'], // 如果选择 custom,后面会让你再输入一个自定义的 scope。也可以不设置此项,把后面的 allowCustomScopes 设置为 true
134 | ].map(([value, description]) => {
135 | return {
136 | value,
137 | name: `${value.padEnd(30)} (${description})`,
138 | }
139 | }),
140 |
141 | subjectLimit: 100, // subject 限制长度
142 | skipQuestions: ['body', 'footer'], // 跳过问题:详细描述 issue相关
143 | }
144 | ```
145 | ::
146 |
147 |
148 |
149 | ## 指定规范生成CHANGELOG
150 |
151 | ### conventional-changelog
152 |
153 | ::tabs
154 | ---
155 | tabs: [ 'bash', 'package.json' ]
156 | ---
157 |
158 | #bash
159 | ```bash
160 | # 一个符合 Angular 团队规范的 preset,按照我们指定的规范生成 commit message。
161 | pnpm add -D cz-conventional-changelog
162 |
163 | # 【可选】全局模式下, 需要 ~/.czrc 配置文件, 为 commitizen 指定 Adapter。
164 | echo '{ "path": "cz-conventional-changelog" }' > ~/.czrc
165 | ```
166 |
167 | #package.json
168 | ```json
169 | {
170 | "config": {
171 | "commitizen": {
172 | "path": "node_modules/cz-conventional-changelog"
173 | }
174 | }
175 | }
176 | ```
177 | ::
178 |
--------------------------------------------------------------------------------
/content/docs/300.standard-commit/3.changelog.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'changelog'
3 | ---
4 |
5 | ### 生成提交日志
6 |
7 | ::tabs
8 | ---
9 | tabs: [ 'bash', 'package.json' ]
10 | ---
11 |
12 | #bash
13 | ```bash
14 | pnpm add standard-version -D
15 | ```
16 |
17 | #package.json
18 | ```json
19 | {
20 | "scirpt": {
21 | "release": "standard-version", // 默认 更新patch
22 | // --release-as === -r 指定版本号
23 | // standard-version -r 2.0.0-test // 自定义修改版本
24 | "release:major": "standard-version -r major -n", // 更新主版本 1.0.0 -> 2.0.0
25 | "release:minor": "standard-version -r minor -n", // 更新次版本 1.0.0 -> 1.1.0
26 | "release:patch": "standard-version -r patch -n", // 更新修订版 1.0.0 -> 1.0.1
27 | // --prerelease === -p 预发版本命名
28 | "prerelease:alpha": "standard-version -p alpha -n", // 更新alpha 1.0.0 -> 1.0.0-alpha.0 【再次执行 -alpha.0 -> -alpha.1】
29 | "prerelease:beta": "standard-version -p beta -n", // 更新beta 1.0.0 -> 1.0.0-beta.0
30 | "prerelease:rc": "standard-version -p rc -n" // 更新rc 1.0.0 -> 1.0.0-rc.0
31 | // --tag-prefix === -t 版本 tag 前缀
32 | // standard-version --tag-prefix "stable-" // 1.0.0 -> stable-v1.0.0
33 | // 查看更多命令
34 | // standard-version --help
35 | }
36 | }
37 | ```
38 |
39 | ::
40 |
41 | ### 语义化版本规范
42 |
43 | [语义化版本 semver](https://semver.org/){.doclink}
44 |
45 | ```bash
46 | # alpha: 内部测试版本, 一般不向外部公开, 会有很多 bug, 也可能随时删除
47 | # beta: 公测版本, 会有一些 bug, 但是基本上可以在 API 不大变的情况下进行升级
48 | # rc: 也叫做 gamma, 代表发行候选版本, 也就是在 beta 版本中没有发现 bug, 随时都可能发布正式版本
49 | # stable: 稳定版本, 一般不再对这个版本进行功能性修改, 只修复 bug
50 |
51 | Example:
52 | 1.0.0
53 | 1.0.0-stable
54 | 1.0.0-rc.1
55 | 1.0.0-rc
56 | 1.0.0-beta.1
57 | 1.0.0-beta
58 | 1.0.0-alpha.beta
59 | 1.0.0-alpha.985211
60 | 1.0.0-alpha.1
61 | 1.0.0-alpha
62 | ```
63 |
--------------------------------------------------------------------------------
/content/docs/300.standard-commit/4.git.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Git技巧'
3 | description: 'Git实战技巧'
4 | ---
5 |
6 | ## 账户配置
7 |
8 | ### 配置全局账户
9 |
10 | ```bash
11 | git config --global user.name "xxx"
12 | git config --global user.email ""
13 | ```
14 |
15 | ### 配置本地账户
16 |
17 | ```bash
18 | git config user.name "xxx"
19 | git config user.email ""
20 | ```
21 |
22 | ### SSH 本地配置多个Git账户
23 |
24 | ```bash
25 | # 步骤一:为每个Git账号生成一个SSH密钥对
26 | ssh-keygen -t rsa -C "youremail_github@example.com" -f ~/.ssh/id_rsa_github_user1
27 | ssh-keygen -t rsa -C "youremail_github@example.com" -f ~/.ssh/id_rsa_github_user2
28 |
29 | # 步骤二:配置SSH客户端
30 | # 编辑~/.ssh/config文件:
31 | touch ~/.ssh/config
32 | open ~/.ssh/config
33 |
34 | # 在~/.ssh/config文件中,为每个Git服务添加配置:
35 | # GitHub account
36 | Host github_user1
37 | HostName github.com
38 | User git
39 | IdentityFile ~/.ssh/id_rsa_github_user1
40 | Host github_user2
41 | HostName github.com
42 | User git
43 | IdentityFile ~/.ssh/id_rsa_github_user2
44 |
45 | # 步骤三:将公钥添加到对应的Git账号中
46 | # 复制到对应 GitHub Gitee GitLab 的SSH key设置页面中
47 | cat ~/.ssh/id_rsa_github_user1.pub
48 | cat ~/.ssh/id_rsa_github_user2.pub
49 |
50 | # 测试SSH连接: ssh -T [config文件配置的User]@[config文件配置的Host]
51 | ssh -T git@github_user1
52 | ssh -T git@github_user2
53 |
54 | # clone 远程仓库
55 | SSH远程地址:git@github.com:[用户名]/[仓库地址].git
56 | 改成:git@[ssh config 配置的 HOST]:[用户名]/[仓库地址].git
57 |
58 | # 多账号使用问题:指向SSH仓库地址
59 | git remote set-url origin git@gitee.com:[用户名]/[仓库地址].git
60 | ```
61 |
62 |
63 |
64 | ## 命名&操作
65 |
66 | ### 分支命名
67 |
68 | ```bash
69 | feature/xxx # 功能分支
70 | bugfix/xxx # bug修复分支
71 | hotfix/xxx # 紧急修复分支
72 | release/xxx # 发布分支
73 | ```
74 |
75 | ### 查看日志
76 |
77 | ```bash
78 | git log # 查看提交历史,包括所有分支和标签的提交记录
79 | git log --oneline # 查看简约版历史记录
80 | git log --graph # 查看分支合并图
81 | git reflog # 查看 git 引用日志,查看 HEAD 移动和操作
82 | ```
83 |
84 | ### vim 编辑器
85 |
86 | ```bash
87 | # 按 i 进入编辑模式,按 ESC 退出编辑模式
88 | # :wq 保存并退出
89 | # :q! 不保存退出
90 | # 修改commit的记录
91 | ```
92 |
93 |
94 |
95 | ## commit
96 |
97 | ### 文件名大小写敏感问题
98 |
99 | ```bash
100 | git config core.ignorecase false
101 | ```
102 |
103 | ### 暂存区存储、恢复
104 |
105 | ```bash
106 | git stash # 把当前工作现场“储藏”起来
107 | git stash pop # 恢复储藏内容
108 | git stash list # 查看储存列表
109 | git stash apply stash@{0} # 多次stash后,恢复指定的stash
110 | ```
111 |
112 | ### 合并 commit
113 |
114 | ```bash
115 | # 1、使用命令打开文本编辑器,会出现最近的commit历史(顶部为旧记录)
116 | git rebase -i HEAD~2 # 合并最近两次commit
117 | # 2、将需要合并的commit前面的pick改为s
118 | # 3、保存退出 :wq
119 | # 4、会出现一个新的文本编辑器,将需要合并的commit信息合并
120 | # 5、保存退出 :wq
121 | # 6、会出现冲突,可以强制push
122 | $ git push -f
123 | ```
124 |
125 |
126 |
127 | ## 分支
128 |
129 | ### 分支操作
130 |
131 | ```bash
132 | git branch # 创建分支
133 | git checkout || git switch # 切换分支
134 | git checkout -b || git switch -c # 创建并切换分支
135 | git branch -d # 删除分支
136 | git branch -D # 强行删除分支
137 | git push origin --delete # 删除远程分支
138 | ```
139 |
140 | ### 合并分支
141 |
142 | ```bash
143 | git cherry-pick # 复制一个特定的提交到当前分支
144 |
145 | # 合并方式一:merge
146 | # merge 会把合并前的分支的提交历史原封不动的拷贝过来
147 | git merge # 合并分支
148 | git merge --no-ff -m # 在合并分支时添加合并描述
149 |
150 | # 合并方式二:rebase merge
151 | # 保留提交的作者信息,同时可以合并commit历史
152 | # 完美的解决了 squash merge 定位不到原开发者的问题
153 | git checkout dev
154 | git rebase -i master # 通过 vi 手动调整commit历史
155 | git checkout master
156 | git merge dev
157 | ```
158 |
159 | ### 撤销最近的一次合并
160 |
161 | ```bash
162 | git reflog # 查看 Git 操作历史
163 | git reset --hard HEAD~1 # 方式一:完全丢弃你的更改
164 | git reset --soft HEAD~1 # 方式二:保留你的更改,并将它们移回工作区
165 | git push -f origin # 强制推送你的更改到远程仓库
166 | ```
167 |
168 |
169 |
170 | ## 发布
171 |
172 | ### 打 tag 标签
173 |
174 | ```bash
175 | git tag # 列出所有 tag
176 | git tag -a stable-v1.0.0 -m 'xx功能需求稳定版本1.0.0' # 添加 tag
177 | git tag -d # 删除某个标签
178 | git show # 显示标签对应提交记录的具体信息
179 | git push # 推送某个标签到远程仓库
180 | git push --delete # 删除远程仓库中的某个标签
181 | ```
182 |
--------------------------------------------------------------------------------
/content/docs/300.standard-commit/_dir.yml:
--------------------------------------------------------------------------------
1 | title: 提交规范
2 |
--------------------------------------------------------------------------------
/content/docs/400.standard-dev/0.html.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'html'
3 | description: '关于 HTML5 标签元素、api'
4 | ---
5 |
6 | ## 元素语义化
7 |
8 | ### 元素语义化好处
9 |
10 | - 利于 SEO(搜索引擎优化)
11 | - 利于无障碍访问
12 | - 利于浏览器的插件分析网页
13 |
14 | [HTML5 标签含义之元素周期表](https://www.xuanfengge.com/funny/html5/element/){.doclink}
15 |
16 | ### 资源提示符
17 |
18 | 优化网页性能,减少加载时间
19 |
20 | - async:异步加载 JS,加载完立即执行(适用于独立、不依赖 DOM 的脚本)
21 | - defer:异步加载 JS,DOM 解析后按顺序执行(适用于需要按顺序执行的 JS)
22 | - preload:预加载当前页面关键资源(字体、CSS、JS、视频)
23 | - prefetch:预取未来可能需要的资源(下一页的 JS、CSS、图片等)
24 | - dns-prefetch:提前解析域名(适用于跨域资源,如 CDN)
25 | - preconnect:提前建立连接(适用于远程 API、CDN 资源)
26 | - prerender:预渲染整个页面(适用于高概率访问的下一页)
27 | ```html
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | ```
43 |
--------------------------------------------------------------------------------
/content/docs/400.standard-dev/1.var.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'var'
3 | description: '关于变量、参数、函数、类名等命名规范'
4 | ---
5 |
6 | ## CSS
7 |
8 | ### BEM 命名规范
9 |
10 | ::card
11 | BEM:块(block)、元素(element)、修饰符(modifier)。
12 | 中划线(-):块与块、元素与元素,多个单词之间的连接。
13 | 单下划线(_):块、元素的状态。
14 | 双下划线(__):块与元素之间的连接。
15 |
16 | 布局(.g-)、模块(.m-)、元件(.u-)、功能(.f-)、皮肤(.f-)、状态(.z-)
17 | ::
18 |
19 | ### 属性规范
20 |
21 | ::card
22 | 布局定位属性:display / position / float / clear / visibility / overflow
23 | 自身属性:width / height / margin / padding / border / background
24 | 文本属性:color / font / text-decoration / text-align / vertical-align / white- space / break-word
25 | 其他属性(CSS3):content / cursor / border-radius / box-shadow / text-shadow / background: linear-gradient
26 | ::
27 |
28 |
29 |
30 | ## JS
31 |
32 | ### 变量
33 |
34 | ```js
35 | // 命名方法:camelCase
36 | // 命名规范:类型 + 对象描述或属性的方式
37 |
38 | // bad
39 | const getTitle = 'LoginTable'
40 | // good
41 | const tableTitle = 'LoginTable'
42 | ```
43 |
44 | ### 常量
45 |
46 | ```js
47 | // 命名方法:全部大写下划线分割
48 | const MAX_COUNT = 10
49 | const URL = 'http://test.host.com'
50 | ```
51 |
52 | ### 方法
53 |
54 | ```bash
55 | # 命名方法:camelCase
56 | # 命名规范:动词 + 名词形式
57 | # can has is get set
58 |
59 | # 1、普通情况下,使用动词 + 名词形式
60 | # bad
61 | go、nextPage、show、open、login
62 | # good
63 | jumpPage、openCarInfoDialog
64 |
65 | # 2、请求数据方法,以 data 结尾
66 | # bad
67 | takeData、confirmData、getList、postForm
68 | # good
69 | getListData、postFormData
70 |
71 | # 3、单个动词的情况
72 | init、refresh
73 | ```
74 |
--------------------------------------------------------------------------------
/content/docs/400.standard-dev/2.notes.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: '注释规范'
3 | ---
4 |
5 | ## 文档注释
6 |
7 | [vscode 插件](https://marketplace.visualstudio.com/items?itemName=OBKoro1.korofileheader){.doclink}
8 |
9 | ```js
10 | /*
11 | * 简述当前文件功能
12 | * @author 作者名称
13 | * @version 版本号 最近编辑时间
14 | * @description 该版本改动信息
15 | */
16 | ```
17 |
18 |
19 |
20 | ## HTML 注释规范
21 |
22 | ### 模块注释
23 | ```html
24 |
25 |
26 | ...
27 |
28 |
29 |
30 |
31 |
32 | ...
33 |
34 |
35 | ```
36 |
37 | ### 嵌套模块
38 | ```html
39 |
40 |
41 |
42 |
43 | ...
44 |
45 |
46 |
47 |
48 | ...
49 |
50 |
51 |
52 |
53 |
54 | ```
55 |
56 | ### 条件注释
57 | ```html
58 |
59 |
60 | 浏览器 不是 IE
61 |
62 |
63 |
66 |
67 |
70 |
71 |
74 |
75 | ```
76 |
77 |
78 |
79 | ## CSS 文件注释
80 |
81 | ### 单行注释
82 | ```css
83 | /* Comment Text */
84 | .jdc {}
85 |
86 | /* Comment Text */
87 | .jdc {}
88 | ```
89 |
90 | ### 模块注释
91 | ```css
92 | /* Module A
93 | ---------------------------------------------------------------- */
94 | .mod_a {}
95 |
96 | /* Module B
97 | ---------------------------------------------------------------- */
98 | .mod_b {}
99 | ```
100 |
101 |
102 |
103 | ## JS 注释规范
104 |
105 | ### 单行注释.js
106 | ```js
107 | // is current tab
108 | const active = true
109 |
110 | // 注释行上面是一个块的顶部时不需要空行
111 | function getType() {
112 | // set the default type to 'no type'
113 | const type = this.type || 'no type'
114 | return type
115 | }
116 |
117 | function fn() {
118 | console.log('fetching type...')
119 |
120 | // set the default type to 'no type'
121 | const type = this.type || 'no type'
122 | return type
123 | }
124 | ```
125 |
126 | ### 特殊标记注释
127 | [Better Comments vscode 注释分类插件](https://marketplace.visualstudio.com/items?itemName=aaron-bond.better-comments){.doclink}
128 | [TODO Highlight vscode 注释关键字高亮插件](https://marketplace.visualstudio.com/items?itemName=wayou.vscode-todo-highlight){.doclink}
129 |
130 | ```js
131 | // TODO:功能未完成,待完善
132 | // FIXME:待修复
133 | // XXX:实现方法待确认
134 | // NOTE:代码功能说明
135 | // HACK:此处写法有待优化
136 | // BUG:此处有 Bug
137 | ```
138 |
139 | ### 函数注释
140 | [JSDoc](http://yuri4ever.github.io/jsdoc/){.doclink}
141 |
142 | ```js
143 | /**
144 | * 方法说明
145 | * @func
146 | * @desc xx函数
147 | * @param {string} a - 参数a
148 | * @param {number} b=1 - 参数b默认值为1
149 | * @param {string} c=1 - 参数c有两种支持的取值 1—表示x 2—表示xx
150 | * @param {object} d - 参数d为一个对象
151 | * @param {string} d.e - 参数d的e属性
152 | * @param {object[]} g - 参数g为一个对象数组
153 | * @param {string} g.h - 参数g数组中一项的h属性
154 | * @param {string} [j] - 参数j是一个可选参数
155 | * @return {返回值类型} 返回值说明
156 | */
157 | ```
158 |
159 | ### 变量注释
160 | ```js
161 | /**
162 | * @type {string | null}
163 | * @desc string或者null
164 | */
165 | let foo
166 | ```
167 |
--------------------------------------------------------------------------------
/content/docs/400.standard-dev/3.mock.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Mock'
3 | description: 'Mock开发使用指南'
4 | ---
5 |
6 | ## 方案一:使用接口管理平台
7 |
8 | [apifox 🌟](https://www.apifox.cn/?utm_source=zhihu&utm_medium=article_10001&utm_content=141425111){.doclink}
9 | [easy-mock 🌟](https://mock.presstime.cn/){.doclink}
10 | [yapi 接口文档](https://hellosean1025.github.io/yapi/documents/index.html){.doclink}
11 | [Postman 接口测试](https://www.postman.com/){.doclink}
12 |
13 |
14 |
15 | ## 方案二:MockJs
16 |
17 | [mock.js](http://mockjs.com/){.doclink}
18 |
19 | ::tabs
20 | ---
21 | tabs: [ 'bash', 'js' ]
22 | ---
23 |
24 | #bash
25 | ```bash
26 | # 安装
27 | pnpm add -D mockjs
28 | # OR
29 |
30 |
31 | # 目录
32 | ├─mock
33 | │ ├─test
34 | │ │ └─index.ts
35 | ```
36 |
37 | #js
38 | ```js
39 | import Mock from 'mockjs'
40 |
41 | const { newsList } = Mock.mock({
42 | 'newsList|80': [{
43 | id: '@increment()',
44 | title: '@ctitle()',
45 | date: '@date("yyyy-MM-dd")',
46 | }],
47 | })
48 |
49 | // 数据随机规则 http://mockjs.com/examples.html
50 | Mock.mock(/\/api\/news\/list/, 'get', (params) => {
51 | console.log(params.url) // '/api/news/list?pageSize=10&pageIndex=1'
52 | const pageIndex = getQuery(params.url, 'pageIndex')
53 | const pageSize = getQuery(params.url, 'pageSize')
54 | const start = (pageIndex - 1) * pageSize
55 | const end = pageIndex * pageSize
56 | const totalPage = Math.ceil(newsList.length / pageSize)
57 | const list = pageIndex > totalPage ? [] : newsList.slice(start, end)
58 | return {
59 | status: 200,
60 | list,
61 | total: newsList.length,
62 | message: '获取新闻列表数据成功',
63 | }
64 | })
65 |
66 | Mock.mock('/api/add/news', 'post', (params) => {
67 | console.log(params.body) // "{title:''}"
68 | const body = JSON.pase(params.body)
69 | newsList.push(Mock.mock({
70 | 'id|+1': '@increment()',
71 | 'title': body.title,
72 | 'date': '@date("yyyy-MM-dd")',
73 | }))
74 |
75 | return {
76 | status: 200,
77 | list: newsList,
78 | total: newsList.length,
79 | message: '添加新闻数据成功',
80 | }
81 | })
82 |
83 | // 使用
84 | axios.get('/api/news/list', {
85 | params: { pageSize: 10, pageIndex: 1 },
86 | })
87 | .then(res => console.log(res))
88 |
89 | axios.post('/api/add/news', { title: '' })
90 | .then(res => console.log(res))
91 | ```
92 |
93 | ::
94 |
95 |
96 |
97 | ## 参考链接
98 |
99 | ### 关于抓包工具
100 |
101 | [Charles](https://www.charlesproxy.com/){.doclink}
102 | [Whistle](http://wproxy.org/whistle/){.doclink}
103 | [Proxyman](https://proxyman.io/){.doclink}
104 |
105 |
106 |
107 | ### 关于服务接口API
108 |
109 | [json-server](https://github.com/typicode/json-server){.doclink}
110 |
--------------------------------------------------------------------------------
/content/docs/400.standard-dev/_dir.yml:
--------------------------------------------------------------------------------
1 | title: 开发规范
2 |
--------------------------------------------------------------------------------
/content/docs/500.stanard-buiild/1.package.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'package'
3 | ---
4 |
5 | [packagejson](https://docs.npmjs.com/cli/v9/configuring-npm/package-json){.doclink}
6 |
7 | ::tabs
8 | ---
9 | tabs: [ 'bash', 'package.json' ]
10 | ---
11 |
12 | #bash
13 | ```bash
14 | # 初始化
15 | npm init
16 |
17 | # 一键初始化
18 | npm init -y
19 | ```
20 |
21 | #package.json
22 | ```json
23 | {
24 | "name": "", // 项目名称
25 | "version": "", // 项目版本(semver)
26 |
27 | "description": "", // 项目描述
28 | "keywords": "", // 关键词
29 | "license": "", // 许可证
30 |
31 | "homepage": "", // 包的项目主页或者文档首页
32 | "bugs": "", // 项目问题跟踪器的 url 和/或应报告问题的电子邮件地址
33 | "repository": "", // 代码托管的位置
34 |
35 | "author": "", // 作者
36 | "contributors": "", // 贡献者
37 |
38 | "files": [], // 设置需要推送到npm的文件
39 | "main": "", // 入口文件
40 | "bin": "", // 自定义命令
41 | "directories": "", // 包安装时,你可以指定确切的位置来放pages、文档、例子等
42 | "types": "", // index.d.ts 位于包的根目录,则不需要标记 types 属性
43 |
44 | "browser": "", // 浏览器
45 |
46 | "scripts": "", // 指定运行脚本命令的 npm 命令行缩写
47 | "config": "", // 用于添加命令行的环境变量
48 |
49 | "dependencies": {}, // 项目运行所依赖的模块
50 | "devDependencies": {}, // 项目开发所需要的模块
51 | "peerDependencies": {}, // 平行依赖允许你说明你的包和其他包版本的兼容性
52 | "optionalDependencies": {}, // 可选依赖项
53 | "bundledDependencies": {}, // 包依赖是发布你的包时将会一起打包的一个包名数组
54 |
55 | "engines": [], // 指定项目 node、npm 版本
56 | "os": [], // 指定模块适用系统
57 | "cpu": [], // 指定模块适用 cpu 架构
58 |
59 | "private": "", // 如果你不想你的包发布到包管理器(npm 或者 私有包管理),设置为 true
60 | "publishConfig": "" // 包名有@符号,例如@username/component,默认为私有包,需配置 { "access": "public" }
61 | }
62 | ```
63 |
64 | ::
65 |
--------------------------------------------------------------------------------
/content/docs/500.stanard-buiild/2.build.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: '构建工具'
3 | ---
4 |
5 | ## 配置构建
6 |
7 | ::tabs
8 | ---
9 | tabs: [ 'base', 'dev', 'prod' ]
10 | ---
11 |
12 | #base
13 | ```md
14 |
15 | 配置 output 输出
16 | 配置 entry 入口
17 | 配置 resolve
18 | 配置 loader:ts、js兼容、vue、css、sass、图片、字体、媒体文件
19 | 配置 plugin:静态资源注入html文件、清理dist目录、热更新
20 | 配置环境变量
21 | ```
22 |
23 | #dev
24 | ```md
25 |
26 | 配置 mode 模式
27 | 配置 devtool 调试工具
28 | 配置 devServer:开发服务器、代理、热更新
29 | ```
30 |
31 | #prod
32 | ```md
33 |
34 | 配置 mode 模式
35 | 依赖构建分析:分析项目体积、测量打包速度
36 | 提取项目依赖、使用CDN
37 | 静态资源优化
38 | 剔除日志、Code Splitting、Tree Shaking、开启GZIP压缩
39 | 查询优化:定向查找、减少执行构建的模块
40 | 构建速度优化:预编译资源模块、多进程多实例打包构建、多进程多实例并行压缩、基础包CDN、持久化缓存
41 | ```
42 | ::
43 |
44 |
45 |
46 | ## 参考链接
47 |
48 | [webpack](https://webpack.js.org/){.doclink}
49 | [vue-cli4-config 配置清单](https://github.com/staven630/vue-cli4-config){.doclink}
50 | [Vite](https://vitejs.dev/){.doclink}
51 | [Rollup](https://rollupjs.org/){.doclink}
52 |
--------------------------------------------------------------------------------
/content/docs/500.stanard-buiild/_dir.yml:
--------------------------------------------------------------------------------
1 | title: 打包
2 |
--------------------------------------------------------------------------------
/content/docs/600.standard-monitor/1.buried.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: '埋点、监控'
3 | ---
4 |
5 | ## 埋点
6 |
7 | ### 手动埋点
8 |
9 | ### 自动埋点
10 |
11 | ### 可视化埋点
12 |
13 |
14 |
15 | ## 监控
16 |
17 | ### 性能监控
18 |
19 | ### 异常监控
20 |
21 | ### 用户体验
22 |
23 |
24 |
25 | ## 参考链接
26 |
27 | [应用实时监控服务ARMS](https://www.alibabacloud.com/help/zh/arms/application-monitoring/developer-reference/arms-sdks){.doclink}
28 | [神策](https://www.sensorsdata.cn/){.doclink}
29 | [sentry](https://github.com/getsentry/sentry){.doclink}
30 | [小程序实时日志](https://developers.weixin.qq.com/miniprogram/dev/framework/realtimelog/){.doclink}
31 |
--------------------------------------------------------------------------------
/content/docs/600.standard-monitor/_dir.yml:
--------------------------------------------------------------------------------
1 | title: 埋点监控
2 |
--------------------------------------------------------------------------------
/content/docs/700.standard-optimize/1.css.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'css'
3 | ---
4 |
5 | ## 代码层面
6 |
7 | - 利用浏览器渲染过程的 分层 优化
8 | - 元素提升为图层,动画在 GPU 中完成,例如 `transform`、`filter`、`position`、`opacity`
9 | - css属性 `will-change` 提高性能
10 | - 降低 reflow 重排(本质是重新计算layout树及后边渲染流程,如布局、分层、绘制)
11 | - 布局耗时 - 几何计算(宽高、margin、padding、字体大小等)
12 | - 修改 dom 结构
13 |
--------------------------------------------------------------------------------
/content/docs/700.standard-optimize/2.js.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'JS'
3 | ---
4 |
5 | ## 代码层面
6 |
7 | ### 执行
8 | - 避免内存泄漏(全局变量、闭包、DOM 元素的引用、定时器、控制台打印)
9 | - 有繁重计算的代码抽离到 Web Worker
10 |
11 | ### 渲染
12 | - 分批渲染使用 `requestAnimationFrame` 代替 `setTimeout`
13 | - 页面添加多个元素时,使用 `DocumentFragment` 组装后一次性添加到页面
14 | - 页面添加多个元素时,使用 `requestIdleCallback` 函数将在浏览器空闲时期被调用
15 | ```js
16 | function performanceChunk(data) {
17 | let i = 0
18 | function _run() {
19 | if (i >= data.length)
20 | return
21 | requestIdleCallback((idle) => {
22 | while (idle.timeRemaining() > 0 && i < data.length) {
23 | const div = document.createElement('div')
24 | div.textContent = data[i]
25 | document.body.appendChild(div)
26 | i++
27 | }
28 | _run()
29 | })
30 | }
31 | _run()
32 | }
33 | ```
34 | ### 脚本
35 | - 使用 `async` 或 `defer` 属性加载脚本
36 | - 使用 `preload` 或 `prefetch` 属性加载脚本
37 |
--------------------------------------------------------------------------------
/content/docs/700.standard-optimize/3.resource.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: '静态资源'
3 | ---
4 |
5 | ### 资源优先级
6 | - 预取回 Prefetch
7 | - 预加载 Preload
8 | - 预连接 Preconnect
9 | - DNS预取回 DNS-Prefetch
10 |
11 | ### 图片
12 | - 加载:懒加载、预加载
13 | - 图片分割 & 雪碧图
14 | - 图片格式
15 | - 建议使用循环播放的 video 或者 WebP 代替 gif
16 | - 使用 WebP 将减少图像大小,使用 JPEG 将提高图像的可感知性
17 | - 为不同 DPR 屏幕提供最适合的图片尺寸
18 | - 使用图片时尽可能使用具有 srcset,sizes 和 元素的响应式图像
19 |
--------------------------------------------------------------------------------
/content/docs/700.standard-optimize/3.vue.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Vue'
3 | ---
4 |
5 | ### 代码层面
6 | - v-for 使用 key(有利于列表变动时,尽量少的删除、新增、改动元素)
7 | - 合理使用冻结对象(提升效率 Object.freeze(obj),冻结的对象不会响应式)
8 | - 使用函数式组件(减少组件初始化的过程,内存更少,不会创建实例对象)
9 | - 使用计算属性(某个数据多次使用,并且数据时通过计算得到的,通过计算属性进行缓存)
10 | - 非实时绑定的表单项(v-modal会导致数据实时变化,会导致重渲染,合理使用lazy避免)
11 | - 保持对象引用稳定(避免获取到的新数据重新赋值给对象,导致引用变化,页面重新渲染)
12 | - 合理使用 v-show 和 v-if
13 | - 使用延迟装载defer(利用 requestAnimationFrame 事件分批渲染内容)
14 | ```js
15 | // 定义
16 | export default function deferMixins (maxFrameCount) {
17 | return {
18 | data() {
19 | return {
20 | frameCount: 0
21 | }
22 | },
23 | },
24 | mounted() {
25 | function refreshFrameCount() {
26 | requestAnimationFrame(() => {
27 | this.frameCount++
28 | if (this.frameCount < maxFrameCount)
29 | refreshFrameCount()
30 | })
31 | }
32 | refreshFrameCount()
33 | },
34 | methods: {
35 | defer(showInFrameCount) {
36 | return this.frameCount >= showInFrameCount
37 | }
38 | }
39 | }
40 |
41 | // 使用
42 | deferMixins(10) // 分是个片段
43 |
// 片段1时渲染
44 |
// 片段10时渲染
45 | ```
46 | - 使用 KeepAlive 复用组件(避免组件重复的创建、销毁带来的性能损耗)
47 | - 长列表优化
48 | - 及时清除组件中的副作用(比如 setInterval 等)
49 |
50 | ### 配置构建
51 | - 打包体积优化
52 | - 组件按需加载
53 | - 组件异步加载
54 | - 路由懒加载
55 | - 生产环境排除打包使用CDN
56 | - 打包移除日志打印
57 |
--------------------------------------------------------------------------------
/content/docs/700.standard-optimize/4.mini-program.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: '小程序'
3 | ---
4 |
5 | ### 界面
6 |
7 | - 图片:避免使用大图;
8 | - 图片:避免滥用 image 组件的 widthFix/heightFix 模式;
9 | - 组件:骨架屏、占位组件、虚拟组件
10 | - 节点:减少组件数量、减少节点嵌套层级,总页面节点数少于1000个,节点树深度层级少于30层,子节点数不大于60个
11 | - 滚动组件:开启惯性滚动 `-webkit-overflow-scrolling: touch;`
12 | - 交互通信:使用hover-class实现按钮的单击态、`使用recycle-view & recycle-item 虚拟DOM组件`
13 | - 交互通信:防止用户的左滑或者按键返回误操作,导致整个页面回退的问题
14 | - 交互通信:scroll-view尤其注意视图层和逻辑层频繁进行通讯;
15 | - 交互通信:长列表使用ulist,具有自动回收机制;
16 | - 提取组件:微博长列表页面,点击一个点赞图标,赞数要立即+1,此时这个点赞按钮一定要做成组件。否则这个+1会引发页面级所有数据的从js层向视图层的同步;
17 | - 宽屏适配:leftWindow
18 | - 宽屏适配:topWindow
19 | - 宽屏适配:rightWindow
20 |
21 | ### 加载
22 |
23 | - 新页面渲染和窗体进入动画抢资源,造成页面切换卡顿、掉帧。建议延时100ms~300ms渲染图片或复杂原生组件,分批进行数据通讯,以减少一次性渲染的节点数量;
24 | - 生命周期:提前发起数据请求;
25 | - 生命周期:首屏渲染优化;
26 |
27 | ### 逻辑
28 |
29 | - 列表:动态列表渲染里优化wx:key的使用
30 | - data数据:避免data对象无用数据、合理使用优化数据、减少一次性节点数量,延迟setdata
31 | - 垃圾数据:清理定时器、有一个监听,必须有一个反监听,并及时移除销毁
32 | - 高性能操作:适当监听页面或组件的 scroll 事件;
33 | - 高性能操作:选择高性能的动画实现方式;
34 | - 高性能操作:使用 IntersectionObserver 监听元素曝光;
35 | - 生命周期:避免在 onHide/onUnload 执行耗时操作;
36 | - 启用多线程worker:一些异步处理的任务
37 |
38 | ### 系统
39 |
40 | - 打包:开启摇树优化;
41 | - 打包:页面初始渲染缓存配置 initialRenderingCache;
42 | - 分包:分包预下载;
43 | - 分包:分包异步化(允许通过一些配置和新的接口,使部分跨分包的内容可以等待下载后异步使用,从而一定程度上解决这个限制);
44 | - 代码注入优化(按需注入和用时注入):避免启动页面所在的主包或者分包文件全部加载;
45 | - 代码注入优化(按需注入和用时注入):{"lazyCodeLoading": "requiredComponents"};
46 | - 初始渲染缓存:使视图层不需要等待逻辑层初始化完毕,而直接提前将页面初始 data 的渲染结果展示给用户
47 | - 系统分析:内存分析
48 | - 系统分析:处理内存告警
49 | - 周期性更新:能够在用户未打开小程序的情况下,也能从服务器提前拉取数据
50 | - 数据预拉取:在小程序冷启动的时候通过微信后台提前向第三方服务器拉取业务数据
51 |
52 | ### 实用工具
53 |
54 | - 高性能渲染优先选用 `wxs`
55 | - 高性能渲染优先选用 `renderjs`
56 |
57 | ### 网络层面
58 |
59 | - 减少图片的请求次数 & 压缩图片大小
60 | - 尽可能使用CDN图片或图片链接 & 尽可能使用webp格式图片
61 | - 减少不必要的网络请求,使用本地缓存数据
62 | - 优化网络请求参数,提高网络请求效率
63 | - 优化网络请求的并发数,分优先级
64 |
65 | ### 主包优化
66 |
67 | - 尽可能除tabbar页面外,所有页面都将其放入分包中
68 | - 公共样式提取到主包中,避免重复打包
69 | - 公共样式会被打入每个文件的样式中
70 | - 分包
71 | - 避免多个分包共用一个分包的文件,小程序会默认将公共引用的文件打成主包文件
72 | - 分包引用UI组件,该UI组件将被打入主包
73 |
--------------------------------------------------------------------------------
/content/docs/700.standard-optimize/6.webpack.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Webpack'
3 | ---
4 |
5 | ## 构建性能
6 |
7 | ### 热替换
8 |
9 | ```js
10 | module.exports = {
11 | devServer: {
12 | hot: true,
13 | },
14 | }
15 | ```
16 |
17 | ### 减少模块解析
18 |
19 | ```js
20 | // 针对没有依赖的模块进行不解析配置
21 | module.exports = {
22 | mode: 'development',
23 | module: {
24 | noParse: /jquery/,
25 | },
26 | }
27 | ```
28 |
29 | ### 优化 loader
30 |
31 | - 限制 loader 应用范围
32 | - 缓存 loader 结果 `cache-loader`
33 | - loader 运行开启多线程 `thread-loader`
34 |
35 | ```js
36 | module.exports = {
37 | module: {
38 | rules: [
39 | {
40 | test: /\.js$/,
41 | // lodash 本身使用旧语法,在转化时不需要再进行解析
42 | // exclude: /lodash/,
43 | include: /src/,
44 | use: ['cache-loader', 'thread-loader', 'babel-loader'],
45 | },
46 | ],
47 | },
48 | }
49 | ```
50 |
51 |
52 |
53 | ## 传输性能
54 |
55 | ### externals & CDN
56 |
57 | ::tabs
58 | ---
59 | tabs: [ 'vue.config.js', 'index.html' ]
60 | ---
61 |
62 | #vue.config.js
63 | ```js
64 | let externals = {}
65 | let cdn = {}
66 | if (process.env.NODE_ENV === 'production') {
67 | externals = {
68 | lodash: '_',
69 | echarts: 'echarts',
70 | }
71 | cdn = {
72 | js: [
73 | 'https://cdn.bootcdn.net/ajax/libs/lodash/4.17.21/lodash.min.js',
74 | 'https://cdn.bootcdn.net/ajax/libs/echarts/5.1.2/echarts.min.js',
75 | ],
76 | }
77 | }
78 |
79 | module.exports = {
80 | configureWebpack: {
81 | externals,
82 | },
83 | chainWebpack: (config) => {
84 | config.plugin('html').tap((args) => {
85 | args[0].cdn = cdn
86 | return args
87 | })
88 | },
89 | }
90 | ```
91 |
92 | #index.html
93 | ```html
94 |
95 |
96 |
97 |
98 |
102 |
103 | <%= htmlWebpackPlugin.options.title %>
104 |
105 |
106 |
107 |
108 |
109 | <% for (var js in htmlWebpackPlugin.options.cdn.js) { %>
110 |
111 | <% } %>
112 |
113 |
114 | ```
115 | ::
116 |
117 | ### 自动分包
118 |
119 | ::tabs
120 | ---
121 | tabs: [ 'webpack.config.js' ]
122 | ---
123 |
124 | #webpack.config.js
125 | ```js
126 | module.exports = {
127 | mode: 'production',
128 |
129 | optimization: {
130 | splitChunks: {
131 | // 分包配置
132 |
133 | chunks: 'all',
134 | // maxSize: 60000,
135 | // minChunks: 2,
136 | // minSize: 30000,
137 |
138 | cacheGroups: {
139 | // 属性名是缓存组名称,会影响到分包的chunk名
140 | // 属性值时缓存组的配置,缓存组继承所有的全局配置,也有自己特殊的配置
141 | vendors: {
142 | test: /[\\/]node_modules[\\/]/, // 匹配到相应模块时,将这些模块进行单独打包
143 | priority: -10, // 缓存组优先级,优先级越高,该策略越先进行处理,默认值0
144 | },
145 | default: {
146 | minChunks: 2, // 覆盖全局配置,将最小的chunk引用数改为2
147 | priority: -20, // 优先级
148 | reuseExistingChunk: true, // 重用已经被分离出去的chunk
149 | },
150 | // 举例:样式chunks
151 | style: {
152 | minChunks: 2,
153 | test: /\.css$/,
154 | priority: 0,
155 | },
156 | },
157 | },
158 | },
159 | }
160 | ```
161 | ::
162 |
163 | ### 手动分包
164 |
165 | - 开启 output.library 暴露公共模块
166 | - 用 DllPlugin 创建资源清单
167 | - 用 DllReferencePlugin 使用资源清单
168 |
169 | ::tabs
170 | ---
171 | tabs: [ 'webpack.dll.config.js', 'webpack.config.js', 'package.json', 'index.html' ]
172 | ---
173 |
174 | #webpack.dll.config.js
175 | ```js
176 | // webpack.dll.config.js
177 | const path = require('node:path')
178 | const webpack = require('webpack')
179 |
180 | module.exclude = {
181 | mode: 'production',
182 | entry: {
183 | lodash: ['lodash'],
184 | jquery: ['jquery'],
185 | },
186 | output: {
187 | filename: 'dll/[name].js',
188 | library: '[name]',
189 | },
190 | plugins: [
191 | new webpack.DllPlugin({
192 | path: path.resolve(__dirname, 'dll', '[name].manifest.json'),
193 | name: '[name]',
194 | }),
195 | ],
196 | }
197 | ```
198 |
199 | #webpack.config.js
200 | ```js
201 | module.exports = {
202 | plugins: [
203 | new CleanWebpackPlugin({
204 | cleanOnceBeforeBuildPatterns: ['**/*', '!dll', '!dll/*'],
205 | }),
206 | new webpack.DllReferencePlugin({
207 | manifest: require('./dll/jquery.manifest.json'),
208 | }),
209 | new webpack.DllReferencePlugin({
210 | manifest: require('./dll/lodash.manifest.json'),
211 | }),
212 | ],
213 | }
214 | ```
215 |
216 | #package.json
217 | ```json
218 | {
219 | "script": {
220 | "dll": "webpack --config webpack.dll.config.js"
221 | }
222 | }
223 | ```
224 |
225 | #index.html
226 | ```html
227 |
228 |
229 | ```
230 | ::
231 |
232 | ### 单模块体积优化
233 |
234 | - 压缩代码
235 |
236 | ```js
237 | const CssMinimizerPlugin = require('css-minimizer-webpack-plugin')
238 | const TerserPlugin = require('terser-webpack-plugin')
239 |
240 | module.exports = {
241 | mode: 'production',
242 | optimization: {
243 | // 是否启用压缩,生产环境默认启用
244 | minimize: true,
245 | minimizer: [
246 | // 默认内置 JS 压缩
247 | new TerserPlugin({
248 | terserOptions: {
249 | compress: {
250 | drop_console: true,
251 | },
252 | },
253 | }),
254 |
255 | // CSS 压缩
256 | new CssMinimizerPlugin(),
257 | ],
258 | },
259 | }
260 | ```
261 |
262 | - Tree Shaking
263 | - `mode: 'production'`
264 | - 使用 export {} 导出,而不是用 export default {} 导出
265 | - 使用 import {} from '..' 导出,而不是用 import from '..' 导出
266 | - 标记文件副作用
267 | ```bash
268 | {
269 | "sideEffects": true # 所有模块都有副作用
270 | "sideEffects": [ !"*.css" ] # 指定模块没有副作用
271 | }
272 | ```
273 |
274 | ### 懒加载
275 |
276 | ::tabs
277 | ---
278 | tabs: [ 'util.js', 'index.js' ]
279 | ---
280 |
281 | #util.js
282 | ```js
283 | export { chunk } from 'lodash-es'
284 | ```
285 |
286 | #index.js
287 | ```js
288 | async function onButtonClick() {
289 | const { chunk } = await import('./util.js')
290 | }
291 | ```
292 | ::
293 |
294 | ### GZIP 预压缩
295 |
296 | ::tabs
297 | ---
298 | tabs: [ 'webpack', 'nginx' ]
299 | ---
300 |
301 | #webpack
302 | ```js
303 | // 移除服务器的压缩时间
304 | // npm install --save-dev compression-webpack-plugin
305 | const CompressionPlugin = require('compression-webpack-plugin')
306 |
307 | module.exports = {
308 | plugins: [
309 | new CompressionPlugin({
310 | filename: '[path][base].gz', // 输出文件名,可以自定义
311 | algorithm: 'gzip', // 使用的压缩算法
312 | test: /\.(js|css|html|svg)$/, // 匹配要压缩的文件类型
313 | threshold: 10240, // 只处理大于 10KB 的文件
314 | minRatio: 0.8, // 只有压缩率小于这个比例的文件才会被处理
315 | }),
316 | ],
317 | }
318 | ```
319 |
320 | #nginx
321 | ```bash
322 | http {
323 | gzip_static on;
324 | }
325 | ```
326 |
327 | ::
328 |
329 |
330 |
331 | ## 其他优化
332 |
333 | ### Bundle Analyzer
334 |
335 | ::tabs
336 | ---
337 | tabs: [ 'base', 'webpack', 'package' ]
338 | ---
339 |
340 | #base
341 | ```bash
342 | pnpm add -D webpack-bundle-analyzer
343 | ```
344 |
345 | #webpack
346 | ```js
347 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
348 |
349 | module.exports = {
350 | plugins: [
351 | new BundleAnalyzerPlugin({
352 | analyzerMode: 'server', // 可以设置为 'static'、'server'、'disabled'
353 | openAnalyzer: true, // 是否自动打开浏览器
354 | reportFilename: 'bundle-report.html', // 报告文件名,适用于 'static' 模式
355 | }),
356 | ],
357 | }
358 | ```
359 |
360 | #package
361 | ```json
362 | {
363 | "scripts": {
364 | "analyze": "webpack --config webpack.config.js"
365 | }
366 | }
367 | ```
368 | ::
369 |
--------------------------------------------------------------------------------
/content/docs/700.standard-optimize/7.vite.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'Vite'
3 | ---
4 |
5 | ## 配置方面
6 |
7 | ### 构建 & 加载
8 | - 手动分包
9 | ```ts
10 | // 将开发代码文件和公共工具文件分离
11 | // 开发代码经常改动,导致打包文件指纹有变化,用户访问会重新下载文件
12 |
13 | export default defineConfig({
14 | build: {
15 | rollupOptions: {
16 | // manualChunks: { vendor: ['lodash', 'vue'] }, // 外部依赖少 可以手动添加
17 | manualChunks(id) { // 外部依赖多 在执行时添加
18 | if (id.includes('node_modules')) {
19 | return 'vendor'
20 | }
21 | },
22 | },
23 | },
24 | })
25 | ```
26 |
--------------------------------------------------------------------------------
/content/docs/700.standard-optimize/9.network.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: '网络'
3 | ---
4 |
5 | ## 服务优化
6 |
7 | - 开启 gzip 压缩
8 | - 浏览器缓存
9 | - CDN内容分发 & DNS预解析
10 |
11 |
12 |
13 | ## SEO
14 |
15 | - SSR 服务端渲染
16 | - HTML 文件
17 | - Title(标题)、Description(描述)和 Keywords(关键词)
18 | - Meta 标签使用
19 | - Open Graph 协议
20 | - 结构化数据,例如 JSON-LD
21 | - 代码方面
22 | - HTML 语义化
23 | - a 标签中 rel 属性,nofollow、external
24 | - 额外文件
25 | - 添加 sitemap.xml 站点地图
26 | - 添加 robots.txt 文件
27 | - 各搜索引擎提交站点收录
28 |
29 |
30 |
31 | ## SEO工具
32 |
33 | [xml-sitemaps](https://www.xml-sitemaps.com/){.doclink}
34 | [SEO综合查询](https://seo.chinaz.com/){.doclink}
35 |
36 |
37 |
38 | ## 性能检测工具
39 |
40 | [PageSpeed Insights 网站各项 RUM 数据](https://pagespeed.web.dev/?utm_source=psi&utm_medium=redirect){.doclink}
41 | [WebPageTest 网站速度测试](https://www.webpagetest.org/){.doclink}
42 |
--------------------------------------------------------------------------------
/content/docs/700.standard-optimize/_dir.yml:
--------------------------------------------------------------------------------
1 | title: 性能优化
2 |
--------------------------------------------------------------------------------
/content/docs/800.standard-test/1.unit.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: '单元测试'
3 | ---
4 |
5 | ## vitest
6 |
7 | :::tabs
8 | ---
9 | tabs: [ 'install', 'package.json', 'vite.config.ts' ]
10 | ---
11 |
12 | #install
13 | ```bash
14 | pnpm add -D vitest happy-dom
15 | ```
16 |
17 | #package.json
18 | ```json
19 | {
20 | "scripts": {
21 | "test": "vitest"
22 | }
23 | }
24 | ```
25 |
26 | #vite.config.ts
27 | ```ts
28 | ///
29 | import { defineConfig } from 'vite'
30 |
31 | export default defineConfig({
32 | test: {
33 | environment: 'happy-dom',
34 | },
35 | })
36 | ```
37 | :::
38 |
39 | ### 参考链接
40 |
41 | [vitest](https://github.com/vitest-dev/vitest){.doclink}
42 |
43 | [Vitest Workspaces](https://cn.vitest.dev/guide/workspace.html){.doclink}
44 |
--------------------------------------------------------------------------------
/content/docs/800.standard-test/2.automation.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: '自动化测试'
3 | ---
4 |
5 | ## puppeteer
6 |
7 |
8 |
9 | ## 参考链接
10 | [puppeteer](https://github.com/puppeteer/puppeteer){.doclink}
11 |
--------------------------------------------------------------------------------
/content/docs/800.standard-test/3.e2e.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: '系统测试'
3 | ---
4 |
5 | ## cypress
6 |
7 |
8 |
9 | ## 参考链接
10 |
11 | [cypress](https://github.com/cypress-io/cypress){.doclink}
12 |
--------------------------------------------------------------------------------
/content/docs/800.standard-test/_dir.yml:
--------------------------------------------------------------------------------
1 | title: 测试
2 |
--------------------------------------------------------------------------------
/content/docs/900.standard-deploy/1.server.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: '服务器'
3 | ---
4 |
5 | ## 阿里云服务器
6 |
7 | ::card
8 | 服务器购买
9 | - 国内服务器:阿里云ECS、腾讯云CVM
10 | - 国外服务器:日本Vultr、美国Linode、谷歌云、微软Azure、亚马逊AWS、SiteGround
11 | ::
12 |
13 | - 实例 -> 实例详情 -> 重置密码
14 | - 安全组 -> 安全组详情 -> 添加端口
15 |
16 |
17 |
18 | ## 域名
19 |
20 | ::card
21 | 域名购买
22 | - 国内:万网(阿里)、腾讯
23 | - 国外:GoDaddy
24 | ::
25 |
26 | - 实名认证
27 | - ICP备案
28 | - 域名解析 -> 添加记录
29 | - CDN -> 添加域名 -> 云解析CDN -> 配置CNAME
30 | - SSL证书 -> 添加证书 -> 配置证书 -> 部署CDN -> 配置CDN
31 |
32 |
33 |
--------------------------------------------------------------------------------
/content/docs/900.standard-deploy/14.node.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: '本地部署'
3 | ---
4 |
5 | ## Express部署Vue项目
6 |
7 | ::tabs
8 | ---
9 | tabs: [ 'directory', 'bash', 'app.js' ]
10 | ---
11 |
12 | #directory
13 | ```bash
14 | Express项目
15 | ├── app.js
16 | ├── bin
17 | ├── dist # Vue打包后的文件夹
18 | ├── node_modules
19 | ├── package.json
20 | ├── public
21 | ├── routes
22 | └── views
23 | ```
24 |
25 | #bash
26 | ```bash
27 | npm init
28 | pnpm add -D express
29 |
30 | npx express-generator
31 |
32 | # history模式 刷新页面404的问题
33 | pnpm add -S connect-history-api-fallback
34 | # 访问服务404的问题
35 | pnpm add -D http-proxy-middleware
36 | ```
37 |
38 | #app.js
39 | ```js
40 | // Express app.js
41 | const path = require('node:path')
42 | const express = require('express')
43 | const history = require('connect-history-api-fallback')
44 | const { createProxyMiddleware } = require('http-proxy-middleware')
45 |
46 | const app = express()
47 |
48 | // 配置静态资源
49 | app.use(express.static(path.join(__dirname, 'dist')))
50 |
51 | // history模式,刷新页面404的问题
52 | app.use(history())
53 |
54 | // 访问服务404的问题
55 | app.use(
56 | '/api',
57 | createProxyMiddleware({
58 | target: 'xxx',
59 | changeOrigin: true,
60 | pathRewrite: {
61 | '^/api': '',
62 | },
63 | }),
64 | )
65 |
66 | app.listen(3000, () => {
67 | console.log('Server is running at http://localhost:3000')
68 | })
69 |
70 | module.exports = app
71 | ```
72 |
73 | ::
74 |
--------------------------------------------------------------------------------
/content/docs/900.standard-deploy/15.cicd.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: '静态站点部署'
3 | ---
4 |
5 | ## 参考链接
6 | [GitHub Actions](https://docs.github.com/zh/actions){.doclink}
7 | [Netlify](https://www.netlify.com/){.doclink}
8 | [vercel](https://vercel.com/dashboard){.doclink}
9 | [阿里云效](https://www.aliyun.com/product/yunxiao){.doclink}
10 |
--------------------------------------------------------------------------------
/content/docs/900.standard-deploy/16.devops.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'DevOps'
3 | ---
4 |
5 | ## Linux 软件安装
6 |
7 | ::tabs
8 | ---
9 | tabs: [ 'Docker', 'Nginx', 'MySQL' ]
10 | ---
11 | #Docker
12 | ```bash
13 | # CentOS Docker 安装
14 | # https://docs.docker.com/engine/install/centos/
15 |
16 | # Docker 镜像加速
17 | # https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors
18 |
19 | # 启动 Docker 服务,并让它随系统启动自动加载
20 | sudo systemctl start docker
21 | sudo systemctl enable docker
22 | ```
23 |
24 | #Nginx
25 | ```bash
26 | # =========================== 1. 创建 nginx Dockerfile
27 | sudo mkdir -p /usr/local/nginx
28 | touch Dockerfile
29 |
30 | # =========================== 2. 编辑 Dockerfile
31 | # 使用官方最新的 Nginx 镜像作为基础镜像
32 | FROM nginx:latest
33 | # 维护者信息
34 | LABEL maintainer="LOUSANPANG<1271255653@qq.com>"
35 | # 设置环境变量,避免一些安装包提示的问题
36 | ENV DEBIAN_FRONTEND=noninteractive
37 | # 更新包索引,安装 vim,同时清理缓存以减少镜像体积
38 | RUN apt-get update && \
39 | apt-get install -y vim && \
40 | apt-get clean && \
41 | rm -rf /var/lib/apt/lists/*
42 | # 创建自定义配置目录(如果需要可以修改路径)
43 | # RUN mkdir -p /etc/nginx/conf.d
44 | # 将工作目录设置为 Nginx 的默认配置目录
45 | WORKDIR /etc/nginx
46 | # 暴露端口
47 | EXPOSE 80
48 | # 将主机配置文件或静态资源挂载到容器(如果需要可以添加)
49 | # COPY ./container-mysql.conf /etc/nginx/nginx.conf
50 | # 设置容器启动时运行的默认命令
51 | CMD ["nginx", "-g", "daemon off;"]
52 |
53 | # =========================== 3. 构建镜像
54 | sudo docker build -t container-mysql /usr/local/nginx
55 |
56 | # =========================== 4. 运行容器
57 | sudo docker run --name container-mysql -p 80:80 -d container-mysql
58 |
59 | # =========================== 5. 进入容器并配置nginx.conf
60 | sudo docker exec -it container-mysql /bin/bash
61 | vim /etc/nginx/nginx.conf
62 |
63 | # =========================== 6. 自动化重载
64 | sudo docker exec container-mysql nginx -s reload
65 |
66 | # =========================== 7. 启用、停止、删除
67 | docker start container-mysql
68 | docker stop container-mysql
69 | docker rm -f container-mysql
70 | ```
71 |
72 | #MySQL
73 | ```bash
74 | # =========================== 1. 创建 mysql Dockerfile
75 | sudo mkdir -p /usr/local/docker-mysql
76 | cd /usr/local/docker-mysql
77 | touch Dockerfile
78 |
79 | # =========================== 2. 编辑 Dockerfile
80 | # 使用官方 MySQL 镜像
81 | FROM mysql:latest
82 | # 设置环境变量,用于自动配置
83 | ENV MYSQL_ROOT_PASSWORD=abcd1234 \
84 | MYSQL_DATABASE=my_db \
85 | MYSQL_USER=lousanpang \
86 | MYSQL_PASSWORD=abcd1234
87 | # 设置 MySQL 数据存储目录(可选)
88 | VOLUME /var/lib/mysql
89 | # 暴露 MySQL 默认端口
90 | EXPOSE 3306
91 |
92 | # =========================== 3. 构建镜像
93 | sudo docker build -t container-mysql /usr/local/docker-mysql
94 |
95 | # =========================== 4. 运行容器
96 | docker run -d \
97 | --name container-mysql \
98 | -p 3306:3306 \
99 | -v /mnt/user/mysql-data:/var/lib/mysql \
100 | container-mysql
101 |
102 | # =========================== 5. 进入容器并配置
103 | sudo docker exec -it container-mysql /bin/bash
104 | mysql -u root -p
105 | show databases;
106 | use my_db;
107 | show tables;
108 | exit
109 |
110 | # =========================== 6. 启用、停止、删除
111 | docker ps
112 | docker start container-mysql
113 | docker stop container-mysql
114 | docker rm -f container-mysql
115 |
116 | # =========================== 7. 登录 MySQL 容器
117 | docker exec -it container-mysql mysql -uroot -p
118 | # 查看初始化的数据库和用户
119 | SHOW DATABASES;
120 | SELECT User, Host FROM mysql.user;
121 | ```
122 | ::
123 |
124 |
125 |
126 | ## Docker 与 Nginx 的项目应用
127 |
128 | ::tabs
129 | ---
130 | tabs: [ 'directory', 'docker', 'nginx' ]
131 | ---
132 |
133 | #directory
134 | ```bash
135 | - docker
136 | - nginx.conf
137 | - .dockerignore
138 | - Dockerfile
139 | ```
140 |
141 | #docker
142 | ```bash
143 | FROM nginx:latest
144 | LABEL maintainer="LOUSANPANG<1271255653@qq.com>"
145 |
146 | COPY docker/nginx.conf /etc/nginx/nginx.conf
147 |
148 | RUN mkdir -p /root/www/web/dist
149 | COPY dist /root/www/web/dist
150 |
151 | EXPOSE 80
152 |
153 | CMD ["nginx", "-g", "daemon off;"]
154 | tail -f /var/log/nginx/access_www.log
155 | ```
156 |
157 | #nginx
158 | ```bash
159 | user nginx; # 设置运行Nginx的用户
160 | worker_processes auto; # 自动设置工作进程数
161 |
162 | events {
163 | worker_connections 1024; # 每个进程的最大连接数
164 | }
165 |
166 | http {
167 | include /etc/nginx/mime.types; # MIME类型配置
168 | default_type application/octet-stream; # 默认MIME类型
169 |
170 | sendfile on; # 启用高效文件传输
171 | keepalive_timeout 65; # 保持连接的超时时间
172 |
173 | server {
174 | listen 80; # 监听80端口
175 | server_name localhost; # 根据需要更改为你的域名或IP
176 |
177 | location / {
178 | root /root/qiuyan/web; # 代理到此目录
179 | index index.html index.htm; # 默认文件
180 | try_files $uri $uri/ =404; # 文件查找策略
181 | }
182 |
183 | error_page 404 /404.html; # 404错误页面
184 | location = /404.html {
185 | internal; # 仅内部使用
186 | }
187 |
188 | error_page 500 502 503 504 /50x.html; # 500系列错误页面
189 | location = /50x.html {
190 | internal; # 仅内部使用
191 | }
192 | }
193 |
194 | # 可添加其他server块或配置
195 | }
196 | ```
197 | ::
198 |
199 |
200 |
201 | ## 参考链接
202 |
203 | [NGINX 可视化选项配置](https://www.digitalocean.com/community/tools/nginx?global.app.lang=zhCN){.doclink}
204 | [Nginx安装配置详解](https://mp.weixin.qq.com/s/Cd9T_nhAtJ8hI6waEzZiEg){.doclink}
205 |
--------------------------------------------------------------------------------
/content/docs/900.standard-deploy/2.applet.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: '小程序'
3 | ---
4 |
--------------------------------------------------------------------------------
/content/docs/900.standard-deploy/3.app.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 'App'
3 | ---
4 |
5 | ## 账号注册
6 |
7 | ### Apple 开发者账号注册
8 | - 资料准备
9 | - 注册D-U-N-S邓白氏编码
10 | - 法人名称(记住英文名称,申请开发者账户需用)、法人相关信息(身份证、邮箱、电话)、公司相关信息(营业执照、地址、公司邮箱、电话、公司网站、隐私协议网址)
11 | - 材料上传至 - 邓白氏自助服务平台
12 | - 安装Developer软件
13 | - 登录Apple ID
14 | - 注册Apple Developer Program
15 | - 注册者实名认证 -> 姓氏、名字、身份证号、手机号、人连拍照
16 | - 选择组织开发者 -> 法人相关信息(身份证、邮箱、电话)、公司相关信息(公司邮箱、电话、地址、营业执照、网址)、DUNS相关信息(法人实体英文名称[公司全称英文]、邓白氏编码)、申请人相关信息(身份证件、雇佣证明、员工工牌或名牌)
17 | - 699RMB
18 | - 登录 iOS Dev Center
19 | - 配置证书、文件
20 | - 添加开发者手机
21 |
22 | [最新苹果邓白氏编码申请流程](https://blog.csdn.net/weixin_41474319/article/details/135948716?spm=1001.2101.3001.6650.3&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ECtr-3-135948716-blog-140545518.235%5Ev43%5Epc_blog_bottom_relevance_base7&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ECtr-3-135948716-blog-140545518.235%5Ev43%5Epc_blog_bottom_relevance_base7&utm_relevant_index=6){.doclink}
23 | [注册 D-U-N-S 邓白氏编码](https://support.dnb.com/?CUST=APPLEDEV){.doclink}
24 | [材料上传至 - 邓白氏自助服务平台](https://www.dnbportal.cn/){.doclink}
25 | [注册 `Apple Developer Program`](https://developer.apple.com/cn/support/app-account){.doclink}
26 | [登录 iOS Dev Center](https://developer.apple.com/account){.doclink}
27 |
28 |
29 |
30 | ### Google Play 开发者账号注册
31 |
32 | [完整的Google企业账号申请流程](https://zhuanlan.zhihu.com/p/710460516){.doclink}
33 |
34 |
35 |
36 | ## 打包
37 |
38 | ### 配置签名、证书、描述文件
39 | [iOS 证书和描述文件申请](https://ask.dcloud.net.cn/article/152){.doclink}
40 | [Android 签名证书生成指南](https://ask.dcloud.net.cn/article/35777){.doclink}
41 |
42 |
43 |
44 | ### App 打包配置
45 | [基础配置](https://uniapp.dcloud.net.cn/tutorial/app-base.html){.doclink}
46 | [图标配置](https://uniapp.dcloud.net.cn/tutorial/app-icons.html){.doclink}
47 | [启动界面](https://uniapp.dcloud.net.cn/tutorial/app-splashscreen.html){.doclink}
48 | [功能模块](https://uniapp.dcloud.net.cn/tutorial/app-modules.html){.doclink}
49 | [权限配置](https://uniapp.dcloud.net.cn/tutorial/app-permission-android.html){.doclink}
50 | [其他设置](https://uniapp.dcloud.net.cn/tutorial/app-webview-error.html){.doclink}
51 |
52 |
53 |
54 | ## iOS 上架
55 |
56 | ### TestFlight 内测
57 | - 准备工作
58 | - 苹果开发者官网新增App组
59 | - 打包IOS App
60 | - 使用 `Transporter` 上传包
61 | - 邀请、安装
62 | - 通过公开链接邀请测试员,App 的“TestFlight”页面 --> 按现有的群组 --> 启用公开链接 --> 拷贝链接分享
63 | - 通过电子邮件邀请测试员,并附上用于安装 App 和开始测试的链接
64 | - 测试信息,在 App Store Connect 中相应 App 的“测试信息”页面上设置分享 App 的内容公告
65 | - 内部测试人员也可以使用 TestFlight App 安装 App,通过链接获取兑换码进行安装,该 APP 有新版本会自动更新安装,仅支持OS系统
66 | - 内部100名、外部测试人员10000名,上传构建版本的那一天起,每个构建版本有最多 90 天的时间可供测试
67 |
68 | [TestFlight 指南](https://developer.apple.com/cn/testflight/){.doclink}
69 | [TestFlight APP使用教程](https://testflight.apple.com/){.doclink}
70 | [包上传工具](https://help.apple.com/app-store-connect/#/devb1c185036){.doclink}
71 |
72 |
73 |
74 | ### AppStore 上架
75 | - 登录 AppStore Connect
76 | - 创建 App,配置 App 的基础信息
77 | - 使用 `Transporter` 上传包
78 |
79 |
80 |
81 | ## Android 上架
82 | [国内应用市场上架](https://uniapp.dcloud.net.cn/tutorial/store.html){.doclink}
83 | [合规、隐私协议](https://uniapp.dcloud.net.cn/tutorial/android-store.html){.doclink}
84 |
85 | ### Google Play 上架
86 | - 登录 Google Play Console
87 | - 账号
88 | - 验证组织网站 Google Search Console
89 | - 创建应用,配置应用基础信息
90 | - Graphics
91 | - Logo 512*512
92 | - Feature graphic 1,024*500
93 | - Phone screenshots 16:9 or 9:16
94 | - 7-inch tablet screenshots 16:9 or 9:16
95 | - 10-inch tablet screenshots 16:9 or 9:16
96 | - 上传包
97 | - SDK >= 34
98 |
99 | [Google Play Console](https://play.google.com/console/u/0/signup){.doclink}
100 |
101 |
102 |
103 | ### 国内应用市场
104 |
--------------------------------------------------------------------------------
/content/docs/900.standard-deploy/_dir.yml:
--------------------------------------------------------------------------------
1 | title: 集成部署
2 |
--------------------------------------------------------------------------------
/error.vue:
--------------------------------------------------------------------------------
1 |
14 |
15 |
16 |
17 |
18 |
19 | {{ statusCode }}
20 |
21 |
22 | {{ statusMessage }}
23 |
24 |
25 |
26 |
27 | <!DOCTYPE html>
28 | <html lang="en">
29 | <body>
30 | {{ statusCode }}
31 | {{ statusMessage }}
32 | Go Home
33 | </body>
34 | </html>
35 |
36 |
37 |
38 |
39 |
68 |
--------------------------------------------------------------------------------
/eslint.config.mjs:
--------------------------------------------------------------------------------
1 | // @ts-check
2 | import antfu from '@antfu/eslint-config'
3 | import withNuxt from './.nuxt/eslint.config.mjs'
4 |
5 | export default withNuxt(
6 | antfu(),
7 | )
8 |
--------------------------------------------------------------------------------
/layouts/default.vue:
--------------------------------------------------------------------------------
1 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
40 |
--------------------------------------------------------------------------------
/license:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 LOUSANPANG
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/middleware/analytics.global.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtRouteMiddleware((to, from) => {
2 | // https://nuxt.com/docs/getting-started/routing#route-middleware
3 | // 全局路由中间件
4 | })
5 |
--------------------------------------------------------------------------------
/middleware/auth.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtRouteMiddleware((to, from) => {
2 | // https://nuxt.com/docs/getting-started/routing#route-middleware
3 | // 页面路由中间件
4 | // return navigateTo('/')
5 | })
6 |
--------------------------------------------------------------------------------
/nuxt.config.ts:
--------------------------------------------------------------------------------
1 | export default defineNuxtConfig({
2 |
3 | modules: [
4 | '@nuxt/eslint',
5 | '@nuxt/content',
6 | '@unocss/nuxt',
7 | ],
8 | devtools: { enabled: true },
9 |
10 | content: {
11 | highlight: {
12 | theme: {
13 | default: 'github-dark-dimmed',
14 | },
15 | langs: [
16 | 'js',
17 | 'ts',
18 | 'vue',
19 | 'css',
20 | 'scss',
21 | 'sass',
22 | 'html',
23 | 'bash',
24 | 'md',
25 | 'mdc',
26 | 'json',
27 | ],
28 | },
29 | },
30 |
31 | compatibilityDate: '2024-10-14',
32 |
33 | vite: {
34 | css: {
35 | preprocessorOptions: {
36 | scss: {
37 | api: 'modern-compiler',
38 | },
39 | },
40 | },
41 | },
42 |
43 | eslint: {
44 | config: {
45 | stylistic: true,
46 | standalone: false,
47 | },
48 | },
49 | })
50 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "fe-workflow",
3 | "type": "module",
4 | "license": "MIT",
5 | "engines": {
6 | "node": ">=18.0.0"
7 | },
8 | "scripts": {
9 | "prepare": "husky",
10 | "postinstall": "nuxt prepare && npx only-allow pnpm",
11 | "clean": "nuxt cleanup",
12 | "dev": "nuxt dev",
13 | "build": "nuxt build",
14 | "generate": "nuxt generate",
15 | "preview": "nuxt preview",
16 | "typecheck": "nuxt typecheck",
17 | "upgrade": "nuxt upgrade",
18 | "lint": "eslint .",
19 | "lint:fix": "eslint . --fix"
20 | },
21 | "dependencies": {
22 | "@nuxt/content": "^2.13.4",
23 | "@unocss/reset": "^0.63.6",
24 | "vue": "^3.5.12",
25 | "vue-router": "^4.4.5"
26 | },
27 | "devDependencies": {
28 | "@antfu/eslint-config": "^3.8.0",
29 | "@iconify-json/carbon": "^1.2.3",
30 | "@nuxt/eslint": "^0.6.0",
31 | "@unocss/extractor-mdc": "^0.63.6",
32 | "@unocss/nuxt": "^0.63.6",
33 | "@unocss/transformer-directives": "^0.63.6",
34 | "eslint": "^9.13.0",
35 | "husky": "^9.1.6",
36 | "lint-staged": "^15.2.10",
37 | "nuxt": "^3.13.2",
38 | "sass": "^1.80.3",
39 | "unocss": "^0.63.6"
40 | },
41 | "lint-staged": {
42 | "*": "eslint --fix"
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/pages/concept/[...slug].vue:
--------------------------------------------------------------------------------
1 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/pages/docs/[...slug].vue:
--------------------------------------------------------------------------------
1 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/pages/index.vue:
--------------------------------------------------------------------------------
1 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | FE Engineering Construction Guide Refspec.
47 |
48 |
49 | This operation manual including
50 | design
,
51 | cli
,
52 | specification
,
53 | testing
,
54 | optimization
,
55 | monitoring
,
56 | deployment
,
57 | analysis
. can be applied to your
58 | system design.
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 | {{ TITLE_EN }}
70 |
71 |
72 |
77 |
81 |
82 |
83 | {{ item }}
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
96 |
97 |
106 |
{{ index + 1 }}
107 |
108 | {{ item[0] }}
109 | {{ item[1] }}
110 |
111 |
112 |
113 |
114 |
115 |
116 |
119 |
120 |
121 |
122 |
148 |
--------------------------------------------------------------------------------
/public/content/concept/js_prototype_chain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOUSANPANG/fe-workflow/c90807248b6b40ff70d35b28836b6c1d162ad41d/public/content/concept/js_prototype_chain.png
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOUSANPANG/fe-workflow/c90807248b6b40ff70d35b28836b6c1d162ad41d/public/favicon.ico
--------------------------------------------------------------------------------
/public/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LOUSANPANG/fe-workflow/c90807248b6b40ff70d35b28836b6c1d162ad41d/public/logo.png
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | // https://nuxt.com/docs/guide/concepts/typescript
3 | "extends": "./.nuxt/tsconfig.json"
4 | }
5 |
--------------------------------------------------------------------------------
/types/navigation.ts:
--------------------------------------------------------------------------------
1 | export interface RouteType {
2 | title: string,
3 | _path: string,
4 | icon?: string,
5 | children?: RouteType[]
6 | }
7 |
8 | export interface linkType {
9 | depth: number,
10 | id: string,
11 | text: string,
12 | children?: linkType[]
13 | }
14 | export interface tocType {
15 | title: string,
16 | depth: number,
17 | searchDepth: number,
18 | links: linkType[]
19 | }
20 |
--------------------------------------------------------------------------------
/uno.config.ts:
--------------------------------------------------------------------------------
1 | import extractorMdc from '@unocss/extractor-mdc'
2 | import transformerDirectives from '@unocss/transformer-directives'
3 | import {
4 | defineConfig,
5 | presetIcons,
6 | presetUno,
7 | presetWebFonts,
8 | } from 'unocss'
9 |
10 | export default defineConfig({
11 | theme: {
12 | breakpoints: {
13 | mobile: '320px',
14 | pc: '1280px',
15 | },
16 | colors: {
17 | primary: '#0ea5e9',
18 | success: '#10B981',
19 | warning: '#F59E0B',
20 | danger: '#EF4444',
21 | dark: '#0f172a',
22 | light: '#f8fafc',
23 | hover: '#0ea5e9',
24 | slate: {
25 | 50: '#f8fafc',
26 | 100: '#f1f5f9',
27 | 200: '#e2e8f0',
28 | 300: '#cbd5e1',
29 | 400: '#94a3b8',
30 | 500: '#64748b',
31 | 600: '#475569',
32 | 700: '#334155',
33 | 800: '#1e293b',
34 | 900: '#0f172a',
35 | },
36 | },
37 | },
38 |
39 | presets: [
40 | presetUno(),
41 | presetIcons(),
42 | presetWebFonts({
43 | provider: 'google',
44 | fonts: {
45 | 'ubuntu-sans': 'Ubuntu Sans',
46 | },
47 | }),
48 | ],
49 |
50 | transformers: [
51 | transformerDirectives(),
52 | ],
53 |
54 | extractors: [
55 | extractorMdc(),
56 | ],
57 | })
58 |
--------------------------------------------------------------------------------