├── .gitignore
├── .node-version
├── .npmrc
├── .prettierrc
├── LICENSE
├── README.md
├── docs
├── .vuepress
│ ├── config.js
│ ├── enhanceApp.js
│ ├── public
│ │ ├── _redirects
│ │ ├── geneva-switzerland-narrow.jpg
│ │ ├── geneva-switzerland.jpeg
│ │ ├── js-logo-vue-color.png
│ │ ├── js-logo.jpg
│ │ ├── js-nation-square-blue.png
│ │ ├── js-nation-square.png
│ │ └── photo-1483653085484-eb63c9f02547.jpeg
│ ├── sidebar.js
│ ├── styles
│ │ ├── index.styl
│ │ └── palette.styl
│ └── vue-redirect.js
├── README.md
└── note
│ ├── 00.resources
│ ├── 1.awesome-tools.md
│ ├── 2.where-do-i-learn-from.md
│ ├── 3.my-reading-list.md
│ ├── 4.crash-course-study-skills.md
│ ├── 5.using-english.md
│ └── the-digital-productivity-pyramid.jpeg
│ ├── 02.workspace
│ ├── 0.mac.md
│ ├── 1.chrome.md
│ └── 2.vscode.md
│ ├── 08.misc
│ ├── clean-a-keyboard.md
│ ├── gaming-set.md
│ ├── linux-basic-security.md
│ ├── my-video-player-shortcuts.md
│ ├── scc
│ │ ├── count-lines-of-code.md
│ │ └── img
│ │ │ ├── time-cloc-babel-fs8.png
│ │ │ ├── time-loc-babel-fs8.png
│ │ │ ├── time-scc-babel-fs8.png
│ │ │ └── time-tokei-babel-fs8.png
│ └── study
│ │ ├── dont-waste-your-time-and-money.md
│ │ ├── study-fortune.md
│ │ └── why-we-need-to-study.md
│ ├── 10.frontend
│ ├── 01.web
│ │ ├── 1.html.md
│ │ ├── 2.css.md
│ │ ├── 3.javascript-language-basic.md
│ │ ├── 4.typescript-language-basic.md
│ │ └── 5.nodejs-basic.md
│ ├── 02.javascript
│ │ ├── 1.javascript-foundation.md
│ │ ├── 2.introduction-to-javascript.md
│ │ ├── 3.how-to-run-javascript-code.md
│ │ ├── 4.javascript-advanced.md
│ │ ├── 5.syntactic-sugar-in-javascript.md
│ │ ├── 6.javascript-modules.md
│ │ ├── 7.javascript-regular-expression.md
│ │ └── 8.javascript-foundation-legacy-version.md
│ ├── 03.npm
│ │ ├── 1.introduction-to-npm.md
│ │ ├── 2.speeding-up-npm-install.md
│ │ └── 3.set-up-a-private-npm-registry-using-verdaccio.md
│ ├── 04.react
│ │ └── 1.react-hooks.md
│ ├── 05.state-management
│ │ ├── 3.rxjs.md
│ │ └── 4.redux.md
│ ├── 08.javascript-test
│ │ ├── 2.jest.md
│ │ ├── 3.testing-library.md
│ │ └── 4.cypress.md
│ └── frontend-hardcore-overview
│ │ ├── frontend-hardcore-overview.md
│ │ └── img
│ │ ├── dk-effect.jpg
│ │ ├── fe-hardcore-fs8.png
│ │ ├── fe-naive-fs8.png
│ │ ├── go-home.jpeg
│ │ ├── stateofjs2019-dark-fs8.png
│ │ └── stateofjs2019tshirt-illustration.png
│ ├── 20.computer-science
│ ├── 1.crash-course-computer-science.md
│ ├── 2.introduction-to-functional-programming.md
│ └── map-of-computer-science-fs8.png
│ ├── 21.tool-skills
│ ├── 01.git
│ │ ├── git.md
│ │ └── img
│ │ │ ├── git-cheatsheet-cn.jpeg
│ │ │ ├── git-flow-fs8.png
│ │ │ └── git-mindmap-fs8.png
│ ├── 02.markdown.md
│ ├── 31.introduction-to-terminal.md
│ ├── 32.terminal-settings.md
│ ├── iterm2-showcase.png
│ └── shell.md
│ ├── 23.programming-language
│ └── python-language-basic.md
│ ├── 99.about
│ ├── about-me.md
│ ├── about-the-guild.md
│ ├── about-the-site.md
│ └── ref.md
│ └── frontend-development-cookbook.md
├── google3ceb9a355a21cbf4.html
├── package.json
├── pnpm-lock.yaml
├── scripts
├── 301-record.ts
├── check-broken-links.ts
├── list-notes.ts
└── update-config-files.ts
├── tsconfig.json
└── vercel.json
/.gitignore:
--------------------------------------------------------------------------------
1 | # * ----------------------------------------------------------------
2 |
3 | # Created by https://www.gitignore.io/api/node
4 | # Edit at https://www.gitignore.io/?templates=node
5 |
6 | ### Node ###
7 | # Logs
8 | logs
9 | *.log
10 | npm-debug.log*
11 | yarn-debug.log*
12 | yarn-error.log*
13 | lerna-debug.log*
14 |
15 | # Diagnostic reports (https://nodejs.org/api/report.html)
16 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
17 |
18 | # Runtime data
19 | pids
20 | *.pid
21 | *.seed
22 | *.pid.lock
23 |
24 | # Directory for instrumented libs generated by jscoverage/JSCover
25 | lib-cov
26 |
27 | # Coverage directory used by tools like istanbul
28 | coverage
29 | *.lcov
30 |
31 | # nyc test coverage
32 | .nyc_output
33 |
34 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
35 | .grunt
36 |
37 | # Bower dependency directory (https://bower.io/)
38 | bower_components
39 |
40 | # node-waf configuration
41 | .lock-wscript
42 |
43 | # Compiled binary addons (https://nodejs.org/api/addons.html)
44 | build/Release
45 |
46 | # Dependency directories
47 | node_modules/
48 | jspm_packages/
49 |
50 | # TypeScript v1 declaration files
51 | typings/
52 |
53 | # TypeScript cache
54 | *.tsbuildinfo
55 |
56 | # Optional npm cache directory
57 | .npm
58 |
59 | # Optional eslint cache
60 | .eslintcache
61 |
62 | # Optional REPL history
63 | .node_repl_history
64 |
65 | # Output of 'npm pack'
66 | *.tgz
67 |
68 | # Yarn Integrity file
69 | .yarn-integrity
70 |
71 | # dotenv environment variables file
72 | .env
73 | .env.test
74 |
75 | # parcel-bundler cache (https://parceljs.org/)
76 | .cache
77 |
78 | # next.js build output
79 | .next
80 |
81 | # nuxt.js build output
82 | .nuxt
83 |
84 | # vuepress build output
85 | .vuepress/dist
86 |
87 | # Serverless directories
88 | .serverless/
89 |
90 | # FuseBox cache
91 | .fusebox/
92 |
93 | # DynamoDB Local files
94 | .dynamodb/
95 |
96 | # End of https://www.gitignore.io/api/node
97 | n
98 |
99 | # * ----------------------------------------------------------------
100 |
101 | /dist
102 | /public
103 | @pages/
104 |
105 | tempCodeRunnerFile.*
106 | draft/
107 | TODO.*
--------------------------------------------------------------------------------
/.node-version:
--------------------------------------------------------------------------------
1 | 16
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | registry=https://registry.npmmirror.com/
2 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 100,
3 | "arrowParens": "always",
4 | "trailingComma": "all",
5 | "tabWidth": 2,
6 | "singleQuote": true,
7 | "quoteProps": "consistent",
8 | "semi": true,
9 | "useTabs": false,
10 | "overrides": [
11 | {
12 | "files": "*.md",
13 | "options": {
14 | "printWidth": 60
15 | }
16 | }
17 | ]
18 | }
19 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | The MIT License (MIT)
3 |
4 | Copyright (c) 2019 seognil
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | 
4 |
5 |
6 |
7 | 一个前端指南
8 |
9 |
14 |
15 | ## 关于
16 |
17 | > 这个世界需要的不是英雄,而是专家。 —— 利维亚的杰洛特
18 |
19 | 我是 LC,目前是一个想要实现财务和代码双自由的前端工程师。
20 |
21 | 我没有名校光环、也没有大厂背景。2015 年刚毕业的时候,我在上海的一个小网游公司当 IT(就是修电脑的),工资不到三千块,每天的工作就是重装系统,做网线,换鼠标啥的,从早到晚忙忙碌碌。我记得公司边上有一个小饭店,一顿饭两荤一素只要 12 块钱,真好吃,不知道几年过去了有没有涨价。
22 |
23 | 算了一下收支,想要在上海买房得要几百年吧,我想我不能再这样下去了,我得支棱起来啊。后来我开始慢慢自学开发。前端的门槛还是比较低的,电脑浏览器随便打开一个页面,打开控制台,就可以入门了。
24 |
25 | 做开发头几年的时候啥也不会,也没有贵人相助,也难碰到志同道合的伙伴,我走了非常多的弯路。所谓走弯路,是指看了很多良莠不齐的资料,职业规划和心态也迷雾重重,直到 2019 年的时候,我还在用 ES5 和 jQuery 这样的上古技术。而我目前的大部分技能,无论是 React、TypeScript 等现代前端技术;还是算法、设计模式、代码设计原则等科班基础;甚至还有英语、如何与人沟通、写作、理财等等写代码以外的能力。这些实际上都是在两年内起步的。
26 |
27 | 从看菜鸟教程上的简单文档,到翻看 ECMA-262。
28 | 从跟着慕课网的视频教程,到看 Youtube 上的各种 Dev Conf。
29 | 我见到了更广阔的世界,知道从哪获取优质的信息。也对于自己的学习和技术能力越来越有自信,甚至开始有能力帮助周围的朋友和同事。
30 |
31 | 更重要的是,我现在的收入可比当初提高了不知道多少倍,增速比 APPLE 的股票都快(可惜没跑赢 NVIDIA 和 AMD),虽然离财务自由还非常遥远。但是吃饭自由已经不成问题了,去沙县大饭店的时候可以毫无顾忌随便点了~
32 |
33 | 我想,如果我能早点意识到这些,或者有机会告诉十年前的我,努力学习赚钱真的爽。那该多好。
34 | 🎶 那么多如果,可能如果我,可惜没如果 🎶
35 | 还好,现在也不算太晚。种一棵树最好的时间是十年前,其次是现在。
36 |
37 | 本站是我自己在学习前端技能过程中的记录,包含学习路径、学习笔记和采坑经验、写的 Demo 和代码片段、收集整理的自学材料等。
38 |
39 | 写给自己,也写给其他人,希望能够有所帮助。
40 |
41 | 文笔不好,以及还在不断学新东西,旧的知识也有新的理解,慢慢修订和更新吧。
42 |
43 | > 写给我的朋友,东神、阿辉、兔子。
44 |
45 | ## 内容
46 |
47 | 线上地址:
48 |
49 | -
50 |
51 | 镜像地址:
52 |
53 | - :Powered By [Cloudflare Pages](https://dash.cloudflare.com/8144c624bc3fd1e60ba8932cdf4949e4/pages/view/rualc)
54 | - :Powered By [Vercel](https://vercel.com/seognil/rualc)
55 |
56 | 主要文章:
57 |
58 | - 导览
59 | - [前端开发入门指南](https://rualc.me/note/frontend-development-cookbook)
60 | - 系列文章
61 | - [开发环境配置系列](https://rualc.me/workspace/awesome-tools)
62 | - [JavaScript 学习系列](https://rualc.me/frontend/javascript-foundation)
63 | - [Node 基础系列](https://rualc.me/frontend/nodejs-basic)
64 | - [其他学习指南系列](https://rualc.me/study/crash-course-study-skills)
65 |
66 | 以及,授人以鱼不如授人以渔:
67 |
68 | - [我都从哪学习](https://rualc.me/study/where-do-i-learn-from)
69 |
70 | ## WIP
71 |
72 | 写作计划和开发任务现在使用 [GitHub Projects](https://github.com/seognil/fe-foundation/projects/1) 进行管理。
73 |
74 | ## Stargazers over time
75 |
76 | [](https://starchart.cc/seognil/fe-foundation)
77 |
78 | ---
79 |
80 | [捉虫请提 issue](https://github.com/seognil/fe-foundation/issues/new)
81 |
82 | [MIT](LICENSE) - 2019
83 | [知识共享协议 CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh)
84 | Made with ❤️ by Seognil LC
85 |
--------------------------------------------------------------------------------
/docs/.vuepress/config.js:
--------------------------------------------------------------------------------
1 | const dayjs = require('dayjs');
2 | const localizedFormat = require('dayjs/plugin/localizedFormat');
3 | const utc = require('dayjs/plugin/utc');
4 | dayjs.extend(localizedFormat);
5 | dayjs.extend(utc);
6 |
7 | // const sidebar = require('./sidebar');
8 |
9 | const markdownItAttrs = require('markdown-it-attrs');
10 | const { slugify } = require('transliteration');
11 |
12 | // * ----------------------------------------------------------------
13 |
14 | const AboutMe = {
15 | author: {
16 | name: 'Seognil LC',
17 | link: 'https://github.com/seognil',
18 | },
19 | blogger: {
20 | avatar: 'https://avatars.githubusercontent.com/u/5526096?s=400',
21 | name: 'Seognil LC',
22 | slogan: '略懂点前端',
23 | },
24 | social: {
25 | icons: [
26 | {
27 | iconClass: 'fab fa-github',
28 | title: 'GitHub',
29 | link: 'https://github.com/seognil',
30 | },
31 | {
32 | iconClass: 'fab fa-steam',
33 | title: 'Steam',
34 | link: 'https://steamhunters.com/id/seognil/games?sort=completionstate',
35 | },
36 | {
37 | iconClass: 'fab fa-playstation',
38 | title: 'PSN',
39 | link: 'https://psnprofiles.com/seognil?order=percent',
40 | },
41 | {
42 | iconClass: 'fab fa-xbox',
43 | title: 'Xbox',
44 | link: 'https://www.trueachievements.com/gamer/seognil/games#',
45 | },
46 | ],
47 | },
48 | footer: {
49 | createYear: 2019,
50 | copyrightInfo:
51 | 'Seognil LC | MIT License',
52 | },
53 | };
54 |
55 | // * ---------------------------------------------------------------- config
56 |
57 | const config = {
58 | title: '前端指南',
59 | description: '一个前端工程师的自我修养',
60 | head: [
61 | ['link', { rel: 'icon', type: 'image/jpg', href: '/js-nation-square-blue.png' }],
62 | [
63 | 'meta',
64 | {
65 | name: 'keywords',
66 | content: [
67 | 'computer-science',
68 | 'checklist',
69 | 'roadmap',
70 | 'study',
71 | 'frontend',
72 | 'notes',
73 | 'guide',
74 | 'developer',
75 | 'awesome-list',
76 | 'engineer',
77 | ].join(','),
78 | },
79 | ],
80 | ],
81 |
82 | dest: './public',
83 |
84 | theme: 'vdoing',
85 |
86 | // * ------------------------------------------------
87 |
88 | themeConfig: {
89 | ...AboutMe,
90 |
91 | // * ---------------- blog config
92 |
93 | repo: 'seognil/fe-foundation',
94 |
95 | lastUpdated: '上次更新',
96 | // editLinks: true,
97 |
98 | // * ---------------- theme config
99 |
100 | logo: '/js-nation-square-blue.png',
101 |
102 | bodyBgImg: [
103 | // 'https://images.unsplash.com/photo-1542416409-400da26855b5?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=2734&q=80',
104 | // 'https://images.unsplash.com/photo-1561160767-6bbd75de51b8?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=2851&q=80',
105 | // 'https://images.unsplash.com/photo-1483653085484-eb63c9f02547?ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=2850&q=80',
106 | '/photo-1483653085484-eb63c9f02547.jpeg',
107 | ],
108 | bodyBgImgOpacity: 0.1,
109 |
110 | contentBgStyle: 6,
111 |
112 | // * ----------------
113 |
114 | nav: [
115 | { text: '指南', link: '/note/frontend-development-cookbook' },
116 | { text: '资源', link: '/study/where-do-i-learn-from/' },
117 | {
118 | text: '代码训练',
119 | items: [
120 | { text: '刷力扣', link: 'https://github.com/seognil-study/leetcode' },
121 | { text: '手写题', link: 'https://github.com/seognil-study/learn-by-doing' },
122 | ],
123 | },
124 | {
125 | text: '归档',
126 | link: '/archives/',
127 | items: [
128 | { text: '归档', link: '/archives/' },
129 | { text: '分类', link: '/categories/' },
130 | { text: '标签', link: '/tags/' },
131 | ],
132 | },
133 | {
134 | text: '关于',
135 | link: '/about/me',
136 | items: [
137 | { text: '关于我', link: '/about/me/' },
138 | { text: '关于本站', link: '/about/the-site/' },
139 | ],
140 | },
141 | ],
142 |
143 | // sidebarDepth: 3,
144 | sidebar: 'auto',
145 | },
146 |
147 | // * ------------------------------------------------
148 |
149 | plugins: [
150 | [
151 | '@vuepress/last-updated',
152 | {
153 | transformer: (timestamp, lang) => {
154 | return dayjs.utc(timestamp).utcOffset(8).format('lll');
155 | },
156 | },
157 | ],
158 | 'vuepress-plugin-smooth-scroll',
159 | // [
160 | // 'vuepress-plugin-medium-zoom',
161 | // {
162 | // selector: 'img',
163 | // delay: 1000,
164 | // options: {
165 | // // margin: 24,
166 | // background: 'hsla(0, 0%, 0%, 0.1)',
167 | // scrollOffset: 0,
168 | // },
169 | // },
170 | // ],
171 | // [
172 | // 'vuepress-plugin-zooming',
173 | // {
174 | // selector: 'img',
175 | // delay: 1000,
176 | // options: {
177 | // bgColor: 'hsla(0, 0%, 0%, 0.1)',
178 | // // zIndex: 10000,
179 | // },
180 | // },
181 | // ],
182 | ],
183 | cache: false,
184 | markdown: {
185 | lineNumbers: true,
186 |
187 | // https://v1.vuepress.vuejs.org/guide/markdown.html#advanced-configuration
188 | // options for markdown-it-anchor
189 | anchor: {
190 | level: 2,
191 | slugify: (str) => slugify(str),
192 | },
193 | extendMarkdown: (md) => {
194 | md.use(markdownItAttrs, {
195 | leftDelimiter: '{',
196 | rightDelimiter: '}',
197 | });
198 | },
199 | },
200 | extendPageData($page) {
201 | const p = $page;
202 |
203 | // * ---------------- fix markdown-it-attrs for sidebar
204 |
205 | const removeAnchorAttr = (str) => str.replace(/\s{[^}]*}\s*$/, '');
206 |
207 | if (p.title) {
208 | p.title = removeAnchorAttr(p.title);
209 | }
210 |
211 | if (p.headers) {
212 | p.headers.forEach((h) => {
213 | h.title = removeAnchorAttr(h.title);
214 | });
215 | }
216 |
217 | // * ----------------
218 | },
219 | };
220 |
221 | // * ---------------------------------------------------------------- output
222 |
223 | module.exports = config;
224 |
--------------------------------------------------------------------------------
/docs/.vuepress/enhanceApp.js:
--------------------------------------------------------------------------------
1 | const vueRedirect = require('./vue-redirect.js');
2 |
3 | export default ({ router }) => {
4 | router.addRoutes(vueRedirect);
5 | };
6 |
--------------------------------------------------------------------------------
/docs/.vuepress/public/_redirects:
--------------------------------------------------------------------------------
1 | /about/index.html /about/me 301
2 | /about/ /about/me 301
3 | /note/about-the-guild.html /about/the-guild 301
4 | /note/readme.html /about/the-site 301
5 | /note/cloc.html /cs/count-lines-of-code 301
6 | /note/computer-science.html /cs/crash-course-computer-science 301
7 | /note/git.html /cs/git 301
8 | /note/functional-programming.html /cs/introduction-to-functional-programming 301
9 | /note/js-basic.html /cs/javascript-language-basic 301
10 | /note/js-basic /cs/javascript-language-basic 301
11 | /note/markdown.html /cs/markdown 301
12 | /note/python-language-basic.html /cs/python-language-basic 301
13 | /note/python-language-basic /cs/python-language-basic 301
14 | /note/typescript.html /cs/typescript-language-basic 301
15 | /note/css.html /frontend/css 301
16 | /note/cypress.html /frontend/cypress 301
17 | /note/fe-hardcore-overview.html /frontend/frontend-hardcore-overview 301
18 | /note/how-to-run-js.html /frontend/how-to-run-javascript-code 301
19 | /note/html.html /frontend/html 301
20 | /note/js-intro.html /frontend/introduction-to-javascript 301
21 | /note/npm-overview.html /frontend/introduction-to-npm 301
22 | /note/js-advanced.html /frontend/javascript-advanced 301
23 | /note/js-foundation.html /frontend/javascript-foundation 301
24 | /note/js-foundation-old.html /frontend/javascript-foundation-legacy-version 301
25 | /note/js-modular.html /frontend/javascript-modules 301
26 | /note/regexp.html /frontend/javascript-regular-expression 301
27 | /note/jest.html /frontend/jest 301
28 | /note/node-basic.html /frontend/nodejs-basic 301
29 | /note/react-hooks.html /frontend/react-hooks 301
30 | /note/redux.html /frontend/redux 301
31 | /note/redux-observable.html /frontend/redux-observable 301
32 | /note/rxjs.html /frontend/rxjs 301
33 | /note/npm-verdaccio.html /frontend/set-up-a-private-npm-registry-using-verdaccio 301
34 | /note/npm-speedup.html /frontend/speeding-up-npm-install 301
35 | /note/syntactic-sugar.html /frontend/syntactic-sugar-in-javascript 301
36 | /note/testing-library.html /frontend/testing-library 301
37 | /note/clean-keyboard.html /misc/clean-a-keyboard 301
38 | /note/linux-basic-security.html /misc/linux-basic-security 301
39 | /note/fe-development-cookbook.html /note/frontend-development-cookbook 301
40 | /note/fe-development-cookbook /note/frontend-development-cookbook 301
41 | /note/fe-development-cookbook-old.html /note/frontend-development-cookbook 301
42 | /note/fe-development-cookbook-old /note/frontend-development-cookbook 301
43 | /note/frontend-development-cookbook.html /note/frontend-development-cookbook 301
44 | /note/study-methodology.html /study/crash-course-study-skills 301
45 | /note/study-the-costly-way.html /study/dont-waste-your-time-and-money 301
46 | /study/study-the-costly-way.html /study/dont-waste-your-time-and-money 301
47 | /study/study-the-costly-way /study/dont-waste-your-time-and-money 301
48 | /note/study-fortune.html /study/study-fortune 301
49 | /note/study-guild-abstraction.html /study/study-guild-abstraction 301
50 | /note/english-using.html /study/using-english 301
51 | /about/where-do-i-learn-from.html /study/where-do-i-learn-from 301
52 | /about/where-do-i-learn-from /study/where-do-i-learn-from 301
53 | /note/my-reading.html /study/where-do-i-learn-from 301
54 | /note/study-the-only-way.html /study/why-we-need-to-study 301
55 | /study/study-the-only-way.html /study/why-we-need-to-study 301
56 | /study/study-the-only-way /study/why-we-need-to-study 301
57 | /note/my-workstation.html /workspace/awesome-tools 301
58 | /note/chrome.html /workspace/chrome 301
59 | /note/terminal-intro.html /workspace/introduction-to-terminal 301
60 | /note/mac.html /workspace/mac 301
61 | /note/video-hotkey.html /workspace/my-video-player-shortcuts 301
62 | /note/terminal-config.html /workspace/terminal-settings 301
63 | /note/vscode.html /workspace/vscode 301
--------------------------------------------------------------------------------
/docs/.vuepress/public/geneva-switzerland-narrow.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seognil/fe-foundation/74290e0ec2a3f0d8cea2c719c6e1dd21a3c2fbb0/docs/.vuepress/public/geneva-switzerland-narrow.jpg
--------------------------------------------------------------------------------
/docs/.vuepress/public/geneva-switzerland.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seognil/fe-foundation/74290e0ec2a3f0d8cea2c719c6e1dd21a3c2fbb0/docs/.vuepress/public/geneva-switzerland.jpeg
--------------------------------------------------------------------------------
/docs/.vuepress/public/js-logo-vue-color.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seognil/fe-foundation/74290e0ec2a3f0d8cea2c719c6e1dd21a3c2fbb0/docs/.vuepress/public/js-logo-vue-color.png
--------------------------------------------------------------------------------
/docs/.vuepress/public/js-logo.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seognil/fe-foundation/74290e0ec2a3f0d8cea2c719c6e1dd21a3c2fbb0/docs/.vuepress/public/js-logo.jpg
--------------------------------------------------------------------------------
/docs/.vuepress/public/js-nation-square-blue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seognil/fe-foundation/74290e0ec2a3f0d8cea2c719c6e1dd21a3c2fbb0/docs/.vuepress/public/js-nation-square-blue.png
--------------------------------------------------------------------------------
/docs/.vuepress/public/js-nation-square.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seognil/fe-foundation/74290e0ec2a3f0d8cea2c719c6e1dd21a3c2fbb0/docs/.vuepress/public/js-nation-square.png
--------------------------------------------------------------------------------
/docs/.vuepress/public/photo-1483653085484-eb63c9f02547.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seognil/fe-foundation/74290e0ec2a3f0d8cea2c719c6e1dd21a3c2fbb0/docs/.vuepress/public/photo-1483653085484-eb63c9f02547.jpeg
--------------------------------------------------------------------------------
/docs/.vuepress/sidebar.js:
--------------------------------------------------------------------------------
1 | // const sidebar = {
2 | // '/': [
3 | // '/note/frontend-development-cookbook',
4 |
5 | // {
6 | // title: '学习资源',
7 | // collapsable: false,
8 | // children: [
9 | // //
10 | // '/note/00.resources/my-reading-list.md',
11 | // '/note/00.resources/where-do-i-learn-from.md',
12 | // ],
13 | // },
14 |
15 | // {
16 | // title: '学习技巧',
17 | // collapsable: false,
18 | // children: [
19 | // '/note/01.study/crash-course-study-skills.md',
20 | // '/note/01.study/using-english.md',
21 | // '/note/01.study/study-fortune.md',
22 | // '/note/01.study/study-guild-abstraction.md',
23 | // '/note/01.study/why-we-need-to-study.md',
24 | // '/note/01.study/dont-waste-your-time-and-money.md',
25 | // ],
26 | // },
27 |
28 | // {
29 | // title: '开发环境',
30 | // collapsable: false,
31 | // children: [
32 | // '/note/02.workspace/awesome-tools.md',
33 | // '/note/02.workspace/mac.md',
34 | // '/note/02.workspace/chrome.md',
35 | // '/note/02.workspace/vscode.md',
36 |
37 | // {
38 | // title: '终端',
39 | // collapsable: false,
40 | // children: [
41 | // '/note/02.workspace/introduction-to-terminal.md',
42 | // '/note/02.workspace/terminal-settings.md',
43 | // ],
44 | // },
45 |
46 | // {
47 | // title: '脚本',
48 | // collapsable: false,
49 | // children: [
50 | // //
51 | // '/note/02.workspace/my-video-player-shortcuts.md',
52 | // ],
53 | // },
54 | // ],
55 | // },
56 |
57 | // {
58 | // title: '计算机科学',
59 | // collapsable: false,
60 | // children: [
61 | // '/note/03.computer-science/misc/crash-course-computer-science.md',
62 | // '/note/03.computer-science/misc/introduction-to-functional-programming.md',
63 |
64 | // {
65 | // title: '工具',
66 | // collapsable: false,
67 | // children: [
68 | // '/note/03.computer-science/tools/git/git.md',
69 | // '/note/03.computer-science/tools/markdown.md',
70 | // '/note/03.computer-science/tools/scc/count-lines-of-code.md',
71 | // ],
72 | // },
73 |
74 | // {
75 | // title: '语言',
76 | // collapsable: false,
77 | // children: [
78 | // '/note/03.computer-science/programming-language/javascript-language-basic.md',
79 | // '/note/03.computer-science/programming-language/typescript-language-basic.md',
80 | // '/note/03.computer-science/programming-language/python-language-basic.md',
81 | // ],
82 | // },
83 | // ],
84 | // },
85 |
86 | // {
87 | // title: '前端',
88 | // collapsable: false,
89 | // children: [
90 | // '/note/04.frontend/misc/frontend-hardcore-overview/frontend-hardcore-overview.md',
91 |
92 | // {
93 | // title: 'Web',
94 | // collapsable: false,
95 | // children: [
96 | // //
97 | // '/note/04.frontend/web/html.md',
98 | // '/note/04.frontend/web/css.md',
99 | // ],
100 | // },
101 |
102 | // {
103 | // title: 'JavaScript',
104 | // collapsable: false,
105 | // children: [
106 | // '/note/04.frontend/javascript/javascript-foundation.md',
107 |
108 | // '/note/04.frontend/javascript/introduction-to-javascript.md',
109 | // '/note/04.frontend/javascript/how-to-run-javascript-code.md',
110 |
111 | // '/note/04.frontend/javascript/javascript-advanced.md',
112 | // '/note/04.frontend/javascript/syntactic-sugar-in-javascript.md',
113 | // '/note/04.frontend/javascript/javascript-modules.md',
114 | // '/note/04.frontend/javascript/javascript-regular-expression.md',
115 |
116 | // '/note/04.frontend/javascript/javascript-foundation-legacy-version.md',
117 | // ],
118 | // },
119 |
120 | // {
121 | // title: 'Node',
122 | // collapsable: false,
123 | // children: [
124 | // '/note/04.frontend/node/nodejs-basic.md',
125 | // '/note/04.frontend/node/introduction-to-npm.md',
126 | // '/note/04.frontend/node/speeding-up-npm-install.md',
127 | // '/note/04.frontend/node/set-up-a-private-npm-registry-using-verdaccio.md',
128 | // ],
129 | // },
130 |
131 | // {
132 | // title: '工具库',
133 | // collapsable: false,
134 | // children: [
135 | // '/note/04.frontend/javascript-library/rxjs.md',
136 | // '/note/04.frontend/javascript-library/react-hooks.md',
137 | // '/note/04.frontend/javascript-library/redux.md',
138 | // '/note/04.frontend/javascript-library/redux-observable.md',
139 | // ],
140 | // },
141 |
142 | // {
143 | // title: '测试库',
144 | // collapsable: false,
145 | // children: [
146 | // '/note/04.frontend/javascript-test/jest.md',
147 | // '/note/04.frontend/javascript-test/testing-library.md',
148 | // '/note/04.frontend/javascript-test/cypress.md',
149 | // ],
150 | // },
151 | // ],
152 | // },
153 |
154 | // {
155 | // title: '杂项',
156 | // collapsable: false,
157 | // children: [
158 | // //
159 | // '/note/08.misc/linux-basic-security.md',
160 | // '/note/08.misc/clean-a-keyboard.md',
161 | // '/note/08.misc/gaming-set.md',
162 | // ],
163 | // },
164 |
165 | // {
166 | // title: 'About',
167 | // collapsable: false,
168 | // children: [
169 | // '/note/09.about/about-me.md',
170 | // '/note/09.about/about-the-site.md',
171 | // '/note/09.about/about-the-guild.md',
172 | // // '/note/09.about/ref.md',
173 | // ],
174 | // },
175 | // ],
176 | // };
177 |
178 | // module.exports = sidebar;
179 |
--------------------------------------------------------------------------------
/docs/.vuepress/styles/index.styl:
--------------------------------------------------------------------------------
1 | body {
2 | font-family: 'Segoe UI', 'SegoeUI', 'Microsoft YaHei', '微软雅黑', 'SF Pro SC', 'HanHei SC',
3 | 'SF Pro Text', 'Myriad Set Pro', 'SF Pro Icons', 'Apple Legacy Chevron', 'PingFang SC',
4 | 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif;
5 |
6 | /** https://www.apple.com.cn/ */
7 | /* font-family: 'SF Pro SC', 'HanHei SC', 'SF Pro Text', 'Myriad Set Pro', 'SF Pro Icons',
8 | 'Apple Legacy Chevron', 'PingFang SC', 'Helvetica Neue', 'Helvetica', 'Arial', sans-serif; */
9 |
10 | /* * https://www.microsoft.com/zh-cn/ */
11 | /* font-family: 'Segoe UI', SegoeUI, 'Microsoft YaHei', 微软雅黑, 'Helvetica Neue', Helvetica, Arial,
12 | sans-serif; */
13 |
14 | /** vuepress original */
15 | /* font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Cantarell,
16 | Fira Sans, Droid Sans, Helvetica Neue, sans-serif; */
17 | }
18 |
19 | /* * ------------------------------------------------ ui */
20 |
21 | /** hide link right-side icon */
22 | a .icon.outbound {
23 | display: none;
24 | }
25 |
26 | /* * ---------------- sidebar */
27 |
28 | /** sidebar nav toc */
29 | li.sidebar-sub-header a {
30 | color: hsl(0, 0%, 50%);
31 | }
32 |
33 | /** side list item overflow */
34 | /* .right-menu-item a, */
35 | .sidebar-links li a {
36 | display: block;
37 | overflow: hidden;
38 | text-overflow: ellipsis;
39 | white-space: nowrap;
40 | }
41 |
42 | /* * ---------------- */
43 |
44 | /** site inner link */
45 | main a[href^='/'],
46 | main a[href^='#'] {
47 | text-decoration: underline dotted hsla(220, 80%, 60%, 0.5);
48 | color: $accentColor;
49 | }
50 |
51 | /** kbd */
52 | kbd {
53 | background-color: #eee;
54 | border-radius: 3px;
55 | border: 1px solid #b4b4b4;
56 | box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), 0 2px 0 0 rgba(255, 255, 255, 0.7) inset;
57 | color: #333;
58 | display: inline-block;
59 | font-size: 0.85em;
60 | font-weight: 700;
61 | line-height: 1;
62 | padding: 2px 4px;
63 | white-space: nowrap;
64 | }
65 |
66 | /** article blockquote */
67 | blockquote {
68 | color: hsl(0, 0%, 50%);
69 | }
70 |
71 | /* * ---------------- theme override */
72 |
73 | body .theme-vdoing-content a code {
74 | color: unset;
75 | }
76 |
77 | .theme-mode-light .theme-vdoing-content code {
78 | color: hsl(200, 100%, 20%);
79 | }
80 |
81 | /** bold link hack */
82 | body .theme-vdoing-content a strong {
83 | color: hsl(220, 80%, 55%);
84 | font-weight: 700;
85 | }
86 |
87 | /* * ---------------- h2 spliter */
88 |
89 | main h2:nth-of-type(4n + 1) {
90 | border-bottom: 2px solid hsl(0, 50%, 70%);
91 | }
92 | main h2:nth-of-type(4n + 2) {
93 | border-bottom: 2px solid hsl(50, 50%, 70%);
94 | }
95 | main h2:nth-of-type(4n + 3) {
96 | border-bottom: 2px solid hsl(100, 50%, 70%);
97 | }
98 | main h2:nth-of-type(4n + 4) {
99 | border-bottom: 2px solid hsl(220, 50%, 70%);
100 | }
101 |
102 | /* * ---------------- article table */
103 |
104 | main th,
105 | main td {
106 | padding: 0.3em 0.5em;
107 | }
108 |
109 | /* * ---------------- article custom video timeline */
110 |
111 | main .timeline-note + ul a + ul,
112 | main .timeline-note + ul a + ul ul {
113 | line-height: 1.3;
114 | font-size: 14px;
115 | color: hsl(0, 0%, 50%);
116 | }
117 | main .timeline-note + ul code {
118 | padding: 0.05rem 0.4rem;
119 | }
120 |
121 | /* * ---------------- article */
122 |
123 | main.page {
124 | word-break: break-word;
125 | }
126 |
127 | /* * ---------------- cookbook */
128 |
129 | main .cookbook-page ~ ul {
130 | column-count: 3;
131 |
132 | @media (max-width: 1280px) {
133 | column-count: 2;
134 | }
135 | @media (max-width: 720px) {
136 | column-count: 1;
137 | }
138 | }
139 |
140 | /* * ------------------------------------------------ util */
141 |
142 | /* * ---------------- fontawesome import and patch */
143 |
144 | @import url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/fontawesome.min.css);
145 | @import url(https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/brands.min.css);
146 |
147 | .fab.iconfont {
148 | font-family: 'Font Awesome 5 Brands' !important;
149 | line-height: unset;
150 | }
151 |
--------------------------------------------------------------------------------
/docs/.vuepress/styles/palette.styl:
--------------------------------------------------------------------------------
1 | $accentColor = hsl(220, 80%, 60%)
2 | $bannerTextColor = inherit
--------------------------------------------------------------------------------
/docs/.vuepress/vue-redirect.js:
--------------------------------------------------------------------------------
1 | module.exports = [
2 | {
3 | "path": "/about/index.html",
4 | "redirect": "/about/me"
5 | },
6 | {
7 | "path": "/about/",
8 | "redirect": "/about/me"
9 | },
10 | {
11 | "path": "/note/about-the-guild.html",
12 | "redirect": "/about/the-guild"
13 | },
14 | {
15 | "path": "/note/readme.html",
16 | "redirect": "/about/the-site"
17 | },
18 | {
19 | "path": "/note/cloc.html",
20 | "redirect": "/cs/count-lines-of-code"
21 | },
22 | {
23 | "path": "/note/computer-science.html",
24 | "redirect": "/cs/crash-course-computer-science"
25 | },
26 | {
27 | "path": "/note/git.html",
28 | "redirect": "/cs/git"
29 | },
30 | {
31 | "path": "/note/functional-programming.html",
32 | "redirect": "/cs/introduction-to-functional-programming"
33 | },
34 | {
35 | "path": "/note/js-basic.html",
36 | "redirect": "/cs/javascript-language-basic"
37 | },
38 | {
39 | "path": "/note/js-basic",
40 | "redirect": "/cs/javascript-language-basic"
41 | },
42 | {
43 | "path": "/note/markdown.html",
44 | "redirect": "/cs/markdown"
45 | },
46 | {
47 | "path": "/note/python-language-basic.html",
48 | "redirect": "/cs/python-language-basic"
49 | },
50 | {
51 | "path": "/note/python-language-basic",
52 | "redirect": "/cs/python-language-basic"
53 | },
54 | {
55 | "path": "/note/typescript.html",
56 | "redirect": "/cs/typescript-language-basic"
57 | },
58 | {
59 | "path": "/note/css.html",
60 | "redirect": "/frontend/css"
61 | },
62 | {
63 | "path": "/note/cypress.html",
64 | "redirect": "/frontend/cypress"
65 | },
66 | {
67 | "path": "/note/fe-hardcore-overview.html",
68 | "redirect": "/frontend/frontend-hardcore-overview"
69 | },
70 | {
71 | "path": "/note/how-to-run-js.html",
72 | "redirect": "/frontend/how-to-run-javascript-code"
73 | },
74 | {
75 | "path": "/note/html.html",
76 | "redirect": "/frontend/html"
77 | },
78 | {
79 | "path": "/note/js-intro.html",
80 | "redirect": "/frontend/introduction-to-javascript"
81 | },
82 | {
83 | "path": "/note/npm-overview.html",
84 | "redirect": "/frontend/introduction-to-npm"
85 | },
86 | {
87 | "path": "/note/js-advanced.html",
88 | "redirect": "/frontend/javascript-advanced"
89 | },
90 | {
91 | "path": "/note/js-foundation.html",
92 | "redirect": "/frontend/javascript-foundation"
93 | },
94 | {
95 | "path": "/note/js-foundation-old.html",
96 | "redirect": "/frontend/javascript-foundation-legacy-version"
97 | },
98 | {
99 | "path": "/note/js-modular.html",
100 | "redirect": "/frontend/javascript-modules"
101 | },
102 | {
103 | "path": "/note/regexp.html",
104 | "redirect": "/frontend/javascript-regular-expression"
105 | },
106 | {
107 | "path": "/note/jest.html",
108 | "redirect": "/frontend/jest"
109 | },
110 | {
111 | "path": "/note/node-basic.html",
112 | "redirect": "/frontend/nodejs-basic"
113 | },
114 | {
115 | "path": "/note/react-hooks.html",
116 | "redirect": "/frontend/react-hooks"
117 | },
118 | {
119 | "path": "/note/redux.html",
120 | "redirect": "/frontend/redux"
121 | },
122 | {
123 | "path": "/note/redux-observable.html",
124 | "redirect": "/frontend/redux-observable"
125 | },
126 | {
127 | "path": "/note/rxjs.html",
128 | "redirect": "/frontend/rxjs"
129 | },
130 | {
131 | "path": "/note/npm-verdaccio.html",
132 | "redirect": "/frontend/set-up-a-private-npm-registry-using-verdaccio"
133 | },
134 | {
135 | "path": "/note/npm-speedup.html",
136 | "redirect": "/frontend/speeding-up-npm-install"
137 | },
138 | {
139 | "path": "/note/syntactic-sugar.html",
140 | "redirect": "/frontend/syntactic-sugar-in-javascript"
141 | },
142 | {
143 | "path": "/note/testing-library.html",
144 | "redirect": "/frontend/testing-library"
145 | },
146 | {
147 | "path": "/note/clean-keyboard.html",
148 | "redirect": "/misc/clean-a-keyboard"
149 | },
150 | {
151 | "path": "/note/linux-basic-security.html",
152 | "redirect": "/misc/linux-basic-security"
153 | },
154 | {
155 | "path": "/note/fe-development-cookbook.html",
156 | "redirect": "/note/frontend-development-cookbook"
157 | },
158 | {
159 | "path": "/note/fe-development-cookbook",
160 | "redirect": "/note/frontend-development-cookbook"
161 | },
162 | {
163 | "path": "/note/fe-development-cookbook-old.html",
164 | "redirect": "/note/frontend-development-cookbook"
165 | },
166 | {
167 | "path": "/note/fe-development-cookbook-old",
168 | "redirect": "/note/frontend-development-cookbook"
169 | },
170 | {
171 | "path": "/note/frontend-development-cookbook.html",
172 | "redirect": "/note/frontend-development-cookbook"
173 | },
174 | {
175 | "path": "/note/study-methodology.html",
176 | "redirect": "/study/crash-course-study-skills"
177 | },
178 | {
179 | "path": "/note/study-the-costly-way.html",
180 | "redirect": "/study/dont-waste-your-time-and-money"
181 | },
182 | {
183 | "path": "/study/study-the-costly-way.html",
184 | "redirect": "/study/dont-waste-your-time-and-money"
185 | },
186 | {
187 | "path": "/study/study-the-costly-way",
188 | "redirect": "/study/dont-waste-your-time-and-money"
189 | },
190 | {
191 | "path": "/note/study-fortune.html",
192 | "redirect": "/study/study-fortune"
193 | },
194 | {
195 | "path": "/note/study-guild-abstraction.html",
196 | "redirect": "/study/study-guild-abstraction"
197 | },
198 | {
199 | "path": "/note/english-using.html",
200 | "redirect": "/study/using-english"
201 | },
202 | {
203 | "path": "/about/where-do-i-learn-from.html",
204 | "redirect": "/study/where-do-i-learn-from"
205 | },
206 | {
207 | "path": "/about/where-do-i-learn-from",
208 | "redirect": "/study/where-do-i-learn-from"
209 | },
210 | {
211 | "path": "/note/my-reading.html",
212 | "redirect": "/study/where-do-i-learn-from"
213 | },
214 | {
215 | "path": "/note/study-the-only-way.html",
216 | "redirect": "/study/why-we-need-to-study"
217 | },
218 | {
219 | "path": "/study/study-the-only-way.html",
220 | "redirect": "/study/why-we-need-to-study"
221 | },
222 | {
223 | "path": "/study/study-the-only-way",
224 | "redirect": "/study/why-we-need-to-study"
225 | },
226 | {
227 | "path": "/note/my-workstation.html",
228 | "redirect": "/workspace/awesome-tools"
229 | },
230 | {
231 | "path": "/note/chrome.html",
232 | "redirect": "/workspace/chrome"
233 | },
234 | {
235 | "path": "/note/terminal-intro.html",
236 | "redirect": "/workspace/introduction-to-terminal"
237 | },
238 | {
239 | "path": "/note/mac.html",
240 | "redirect": "/workspace/mac"
241 | },
242 | {
243 | "path": "/note/video-hotkey.html",
244 | "redirect": "/workspace/my-video-player-shortcuts"
245 | },
246 | {
247 | "path": "/note/terminal-config.html",
248 | "redirect": "/workspace/terminal-settings"
249 | },
250 | {
251 | "path": "/note/vscode.html",
252 | "redirect": "/workspace/vscode"
253 | }
254 | ]
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | home: true
3 | heroImage: /js-nation-square-blue.png
4 | heroText: 前端指南
5 | tagline: LC 的前端开发技能知识体系
6 | actionText: → 开始阅读 ←
7 | actionLink: /note/frontend-development-cookbook
8 | features:
9 | - title: Ecosystem
10 | details: 精通 VS Code、NodeJS、Vite、Docker 等软件的安装与卸载,配套设施也是必不可少的。
11 | - title: JavaScript
12 | details: 熟练掌握 TypeScript、QraphQL、RxJS 等单词的拼写,学习前端所需的核心语言及开发链路。
13 | - title: Value yourself
14 | details: 枯れた技術の水平思考,Coding With Good Taste,Sic Parvis Magna。
15 | footer: Powered By VuePress | 2022 Seognil LC
16 | ---
17 |
--------------------------------------------------------------------------------
/docs/note/00.resources/1.awesome-tools.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 装了啥(2021)
3 | date: 2021-10-08 10:39:13
4 | permalink: /workspace/awesome-tools
5 | categories:
6 | - 开发环境
7 | tags:
8 | - 工具
9 | - awesome
10 | ---
11 |
12 | # 装了啥(2021)
13 |
14 | ---
15 |
16 | > 参考自:[装了啥 - 云谦](https://github.com/sorrycc/awesome-tools)
17 |
18 | ---
19 |
20 | 
21 |
22 | [Tiago Forte 生产力金字塔](https://fortelabs.co/blog/the-digital-productivity-pyramid/)
23 |
24 | ## 上网
25 |
26 | (paradiseduo)
27 |
28 | ## 软件和工具
29 |
30 | 这些拆到单独的文章了
31 |
32 | - [Mac](/workspace/mac)
33 | - [Chrome](/workspace/chrome)
34 | - [VS Code](/workspace/vscode)
35 |
36 | ## 网站及服务
37 |
38 | - 技术学习和生产
39 | - [Google](https://www.google.com/)
40 | - [YouTube](https://www.youtube.com/)
41 | - [GitHub](https://github.com/)
42 | - [Stack Overflow](https://stackoverflow.com/)
43 | - 网站部署
44 | - [Vercel](https://vercel.com/):静态托管服务
45 | - [阿里云域名](https://wanwang.aliyun.com/):网站域名
46 | - 小工具
47 | - [A SOFT MURMUR](https://asoftmurmur.com/):白噪声
48 | - [astralapp](https://app.astralapp.com/dashboard):GitHub Star 管理器(你是不是也把 star 当收藏夹用?)
49 | - [bundlephobia](https://bundlephobia.com/package/rxjs):npm 包分析
50 |
51 | ## 关爱你的数据
52 |
53 | - [数据备份 之 3-2-1 原则](https://sspai.com/post/39591)
54 | - 云存储(热文件、碎片化信息)
55 | - OneNote:快取笔记
56 | - OneDrive:主要的云盘
57 | - [MEGA sync](https://mega.nz/):可以筛掉 node_modules,放了两个玩具项目和 rualc (因为本地有很多草稿文章)
58 | - Google Photos:手机拍的照片自动备份
59 | - 物理存储(大文件、磁盘、冷存储)
60 | - [选固态](https://zhuanlan.zhihu.com/p/166162142)
61 | - [选机械](https://zhuanlan.zhihu.com/p/147065869)
62 | - 选 U 盘用 SSD:[低功耗 NVME 电流在 2.0A 以下的就不会特别烫](https://www.chiphell.com/forum.php?mod=viewthread&tid=2163456)
63 |
64 | ## 通勤装备
65 |
66 | - 背包:谷歌开发者大会纪念背包
67 | - MacBook Air (M1, 2020) 16G-256G
68 | - 收纳板:cocoon grid it
69 | - 512G U 盘(用来做 Time Machine、iPhone 备份,sata m.2 固态 + 壳)
70 | - 几个小 U 盘(用来做系统安装盘)
71 | - N 合 1 Hub,应急用
72 | - 一堆线材,一堆 Type-C 转接头
73 | - 充电头:倍思 GaN 2C1A 65W
74 | - 紫米无线充电宝
75 | - 其他
76 | - 小米手环 5 NFC 版
77 | - AirPods Pro(噪用和全家桶设备间切换真好用)
78 | - KeySmart 钥匙扣
79 | - 双面公交卡套
80 | - 手机
81 | - 手机
82 | - iPhone 12
83 | - 红米 K40
84 | - 流量
85 | - 移动:8 元低保套餐
86 | - 联通:O 粉卡
87 | - 电信:家里宽带送的
88 |
89 | ## 固定位硬件
90 |
91 | 保证每个工作区都有一组合适的外设,以便接上主力 MBP 提供最大生产力。
92 |
93 | - 每个地方都 +1 的外设
94 | - 34 寸 3440x1440 直屏(大屏即正义!),AOC、ViewSonic 之类的正经牌子哪个有折扣买哪个,平均两千元左右一块,固定位共三块
95 | - GaN 的 2C1A 65W 充电头可以说是很香了,倍思和征拓各两个,一共四个(固定位三个 + 通勤一个)(倍思的指示灯就是太亮了…)
96 | - 小米手写板(有时写写草稿可以说是多快好省了)
97 | - 苹果的触控板(接 Mac)
98 | - 公司
99 | - DockCase P1 QC,作为 MBP 的供电和 USB Hub(考虑到稳定性,视讯线单独接一根在 Type-C 口上)
100 | - 键盘:NIZ Plum 84
101 | - 苹果的鼠标(不常用)
102 | - 出租屋
103 | - Mac Mini M1 8G+256G(可以说是最低配了,冲浪/写玩具用)
104 | - 一台游戏 PC(配置略,最近吃灰了)
105 | - 键盘:Keychron K3(可以不同设备间蓝牙切换)
106 | - 鼠标:罗技 M590(接 PC)
107 | - 铁威马 D4-300
108 | - 希捷酷鹰 4T \* 2 (Raid 1)
109 | - 某便宜的 23 寸显示器(接不同设备应急用)
110 | - 选配结构件
111 | - 爱格升显示器支架(之前用过乐歌的关节处不太行)
112 | - Jugar 极架(金属木板架子,纵向堆设备用)
113 |
114 | ## 游戏机
115 |
116 | - PS4 Pro 港版(借同学了)
117 | - Xbox Series S 德亚(XGPU 真香,手机串流真香)
118 | - Switch 初版 日版(吃灰很久了)
119 |
--------------------------------------------------------------------------------
/docs/note/00.resources/3.my-reading-list.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 看了啥(2021)
3 | date: 2021-10-07 15:32:01
4 | permalink: /study/my-reading-list/
5 | categories:
6 | - 学习渠道
7 | tags:
8 | - awesome
9 | ---
10 |
11 | # 看了啥(2021)
12 |
13 | 来源:实体书、微信读书、听书、速读
14 |
15 | 注:带链接的是我读过的版本,大部分是豆瓣和 B 站
16 |
17 | ## 书
18 |
19 | - 技术
20 | - [游戏设计艺术(第 2 版)](https://book.douban.com/subject/26791007/):CMU 教材,已经出新版了,买新版吧
21 | - 心理
22 | - [《非暴力沟通》 - 马歇尔·卢森堡](https://book.douban.com/subject/3533221/)
23 | - [《被讨厌的勇气》 - 岸见一郎/古贺史健](https://book.douban.com/subject/26369699/):“自我启发之父”阿德勒的哲学课
24 | - [《亲密关系》 - 克里斯多福·孟](https://book.douban.com/subject/26363229/)
25 | - [《正面管教》- 简·尼尔森](https://book.douban.com/subject/3420606/):如何不惩罚、不娇纵地有效管教孩子
26 | - 文学
27 | - 《老人与海》 - 海明威
28 | - 《竹林中》 - 芥川龍之介
29 | - [《小王子》 2015 动画电影](https://movie.douban.com/subject/20645098/)
30 | - 《动物农庄》 - 乔治·奥威尔
31 | - 《献给阿尔吉侬的花束》 - 丹尼尔·凯斯
32 | - B 站 - 李好帅的黄金屋 - 沉浸式读书
33 | - ▶️ [第一集](https://www.bilibili.com/video/BV1mL411b7ek)、[第二集](https://www.bilibili.com/video/BV1Yy4y1G7Ea)、[第三集](https://www.bilibili.com/video/BV1Mg411V7Xg)、[第四集](https://www.bilibili.com/video/BV1bQ4y1a7Es)
34 | - [《献给阿尔吉侬的花束》创作故事](https://www.bilibili.com/read/cv13023094)
35 | - 经济
36 | - [《小狗钱钱》 - 博多·舍费尔](https://book.douban.com/subject/35295592/)
37 | - [《穷爸爸富爸爸》 - 罗伯特·清崎](https://book.douban.com/subject/27153484/)
38 | - 健康
39 | - 《给男孩的身体书》 - 凯莉·邓纳姆
40 | - 《给女孩的身体书》 - 凯莉·邓纳姆
41 | - [《公共营养师 [基础知识]》 - 中国就业培训技术指导中心](https://book.douban.com/subject/20493950/)
42 | - [《全科医学(家庭版)》 - 约翰·莫塔](https://book.douban.com/subject/34986173/)
43 | - 生活
44 | - [《從生命的車窗眺望》 - 星野源](https://book.douban.com/subject/27045708/)
45 | - [《平衡的智慧》 - 帕特·基辛格](https://book.douban.com/subject/1283295/)
46 | - [▶️ B 站 - 幻海航行 - 科幻小说速读](https://space.bilibili.com/193147738)
47 | - 《宇宙过河卒》 - 波尔·安德森
48 | - 《基地》三部曲 - 艾萨克·阿西莫夫
49 | - 《神们自己》 - 艾萨克·阿西莫夫
50 | - 《猎户座防线》 - 史蒂芬·巴克斯特
51 | - 《最后的问题》 - 艾萨克·阿西莫夫
52 |
53 | ## 视频
54 |
55 | - 真人剧
56 | - [▶️ 逃避虽可耻但有用](https://www.bilibili.com/bangumi/play/ss25365/)
57 | - [▶️ 半泽直树 第二季](https://www.bilibili.com/bangumi/play/ss35110/)
58 | - [致命女人 第一季](https://movie.douban.com/subject/30401122/)
59 | - [亿万 第一季](https://movie.douban.com/subject/26200198/)
60 | - [金装律师 第一季](https://movie.douban.com/subject/4842285/)
61 | - 动画
62 | - [▶️ 辉夜大小姐想让我告白? 第二季](https://www.bilibili.com/bangumi/play/ss32982/)
63 | - 攻壳机动队
64 | - [▶️ 第一季](https://www.bilibili.com/bangumi/play/ss1564/)
65 | - [▶️ 第二季](https://www.bilibili.com/bangumi/play/ss1565/)
66 | - [EVA 新剧场版:终](https://movie.douban.com/subject/10428501/)
67 | - [星球大战:幻境](https://movie.douban.com/subject/35284557/)
68 |
--------------------------------------------------------------------------------
/docs/note/00.resources/4.crash-course-study-skills.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 学习方法论
3 | date: 2019-11-23 23:38:58
4 | permalink: /study/crash-course-study-skills
5 | categories:
6 | - 学习技巧
7 | tags:
8 | - crash course
9 | ---
10 |
11 | # 学习方法论
12 |
13 | ## 简介
14 |
15 | ### 什么是 学习方法论
16 |
17 | 我的学习计划系列文章标题一般是「XXX 学习指南」
18 |
19 | 所以这篇文章也可以叫「学习“如何学习”的学习指南」
20 |
21 | ### 为什么要学习 关于学习的方法论
22 |
23 | 像所有其他方法论的目标一样:
24 | 提高 XXX 的执行效率和效果。
25 |
26 | `where (XXX = "学习") => 提高学习的效率和效果`
27 |
28 | ## 学习方法论
29 |
30 | ### 概览
31 |
32 | - 耗时:
33 | - 视频本身大约 100 分钟,但我花了 8 个小时才看完(包括理解和笔记)
34 | - 其他资料断断续续看的,累计可能有 20 个小时
35 | - 难点:
36 | - 养成总结**知识体系**的习惯
37 | - 更好的**时间管理**计划
38 | - 工具:
39 | - 文本编辑器(我用 [VS Code](/workspace/vscode))
40 | - 云存储(我用过的,~~目前主力 Dropbox~~)
41 | - [Dropbox](https://www.dropbox.com/)
42 | - [OneDrive](https://onedrive.live.com/)
43 | - [Google Drive](https://www.google.com/drive/download/backup-and-sync/)
44 | - [MEGA](https://mega.nz/)
45 | - [坚果云](https://www.jianguoyun.com/)
46 |
47 | ### 学习路线
48 |
49 | - 学习 Crash Course Study Skills(按视视频顺序)
50 | - 大脑工作原理
51 | - 笔记和知识管理
52 | - 学习策略
53 | - 心理学技巧
54 | - 考试、工作的准备事项
55 | - 实战
56 | - 立即建立自己的知识体系管理系统
57 | - 在日常工作中进行时间管理
58 | - 健康的作息
59 |
60 | ## 资料
61 |
62 | ### 自学教程
63 |
64 | - CCSS
65 | - [Crash Course Study Skills - YouTube](https://www.youtube.com/watch?v=IhuwS5ZLwKY&list=PL8dPuuaLjXtNcAJRf3bE1IJU6nMfHj86W)
66 | - [学习技能 - bilibili](https://www.bilibili.com/video/av16785517)
67 |
68 | ### 扩展阅读 方法论
69 |
70 | - [费曼学习法](https://wiki.mbalib.com/wiki/%E8%B4%B9%E6%9B%BC%E5%AD%A6%E4%B9%A0%E6%B3%95)
71 | - [艾宾浩斯记忆法](https://wiki.mbalib.com/wiki/%E8%89%BE%E5%AE%BE%E6%B5%A9%E6%96%AF%E8%AE%B0%E5%BF%86%E9%81%97%E5%BF%98%E6%9B%B2%E7%BA%BF)
72 | - [刻意训练](https://www.zhihu.com/question/65785362)
73 | - [小黄鸭调试法](https://zh.wikipedia.org/zh-hans/%E5%B0%8F%E9%BB%84%E9%B8%AD%E8%B0%83%E8%AF%95%E6%B3%95)
74 | - [每月高效工作 200 小时 / Environment Body Mind](https://wanqu.co/a/5765/%E6%AF%8F%E6%9C%88%E9%AB%98%E6%95%88%E5%B7%A5%E4%BD%9C-200-%E5%B0%8F%E6%97%B6/)
75 | - [任务换人有害无益 - Joel 说软件](https://www.kancloud.cn/wizardforcel/joel-on-software/99190)
76 | - [X-Y PROBLEM](https://coolshell.cn/articles/10804.html)
77 | - [提问的智慧](https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/master/README-zh_CN.md)
78 |
79 | ### 扩展阅读 心理学
80 |
81 | - 正面
82 | - [路径依赖](https://wiki.mbalib.com/wiki/%E8%B7%AF%E5%BE%84%E4%BE%9D%E8%B5%96)
83 | - [多看效应](https://wiki.mbalib.com/wiki/%E5%A4%9A%E7%9C%8B%E6%95%88%E5%BA%94)
84 | - [游戏化](https://zhuanlan.zhihu.com/p/45980716)
85 | - [心流]()
86 | - [斯金纳箱](https://www.gcores.com/radios/97874)
87 | - 负面
88 | - [达克效应](https://zh.wikipedia.org/wiki/%E8%BE%BE%E5%85%8B%E6%95%88%E5%BA%94)
89 | - [冒名顶替症候群](https://zh.wikipedia.org/wiki/%E5%86%92%E5%90%8D%E9%A0%82%E6%9B%BF%E7%97%87%E5%80%99%E7%BE%A4)
90 | - [习得性无助](https://www.zhihu.com/question/26518056)
91 | - [分析瘫痪](https://zh.wikipedia.org/wiki/%E5%88%86%E6%9E%90%E7%99%B1%E7%98%93)
92 | - [死锁](https://zh.wikipedia.org/wiki/%E6%AD%BB%E9%94%81)
93 |
94 | ## Crash Course Study Skills 总结
95 |
96 | - 学习系统
97 | - 信息采集
98 | - 采集
99 | - 自然语言也是语法和**含义**
100 | - 语言就是信息,而信息就是一切(出自 [杀死伊芙](https://movie.douban.com/subject/26915602/))
101 | - **记下来**(笔记、书签等)
102 | - 主要信息来源
103 | - 来源(大)
104 | - 权威材料(如官方文档、经典书籍等)
105 | - 学习指南(如个人总结的一篇文章)
106 | - 扩展阅读(以上一般都会有的)
107 | - 来源(小)
108 | - big ideas(要点)
109 | - bullet lists(列表)
110 | - definations(定义)
111 | - **examples**(示例)
112 | - 重要性和优先级
113 | - **argument**(核心概念)
114 | - description(描述)
115 | - context(上下文)
116 | - 三个阅读等级(精读、泛读、跳过)
117 | - SQ3R 阅读法
118 | - 做笔记
119 | - 方式
120 | - 子弹笔记(列表系统)
121 | - 康奈尔笔记(关键目标、笔记、总结)
122 | - 思维导图(脑图、Mind Mapping)
123 | - 提高信噪比(只记关键部分)
124 | - CheatSheet 模式
125 | - 缓冲区(临时信息存储)
126 | - 数据持久化(比如笔记、代码、图片、材料等)
127 | - 设计分层存储系统
128 | - 建立周期性计划
129 |
130 | * 脑科学
131 | - 记忆工作类型
132 | - 记忆(三层模型)
133 | - 传感记忆(视觉听觉信号等)
134 | - 工作记忆(当前工作的信息)
135 | - 长期记忆(记忆)
136 | - **回忆**("学会"的本质)
137 | - 间隔效应
138 | - 艾宾浩斯记忆曲线
139 | - 莱特纳系统
140 | - 知识加工
141 | - 真实性、可视化、独特化、符号化
142 | - 神经突触链接的建立
143 | - 大脑工作的生物资源消耗
144 |
145 | - 心理学
146 | - 专注
147 | - 时间动机理论
148 | - 负面效果
149 | - 定向注意力疲劳
150 | - 刺激反馈成瘾(斯金纳箱、巴普洛夫)
151 | - 抑制机制(嘈杂环境、太难或简单、身体状态、连续工作等)
152 | - 正面措施
153 | - 放慢速度(减少工作记忆负荷)
154 | - 减少被动信息摄入(少刷抖音微博朋友圈,屏蔽环境噪音)
155 | - **停止多任务**(短时休息时也不要切换工作)
156 | - 认知切换惩罚
157 | - 注意力残留
158 | - Environment/Body/Mind
159 | - 番茄工作法
160 | - 压力
161 | - 失败是成功之母
162 | - 压力的生理现象
163 | - 皮质醇激素会阻碍大脑工作
164 | - 来源
165 | - 害怕重复过去的失败(负面认知偏差)
166 | - 害怕未知
167 | - 害怕损失
168 | - 正面措施
169 | - 把烦恼写下来(释放工作记忆)
170 | - 分析过去的错误
171 | - 提高经验水平
172 | - 训练
173 | - 预演
174 | - Memory is context based(记忆是基于场景(上下文)的)
175 | - 寻求专业帮助(心理医生)
176 |
177 | * 健身
178 | - TODO
179 |
180 | - 考试和论文相关
181 | - 略(TODO)
182 |
--------------------------------------------------------------------------------
/docs/note/00.resources/5.using-english.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 英语 训练指南 编程篇
3 | date: 2019-12-14 22:03:19
4 | permalink: /study/using-english
5 | categories:
6 | - 学习技巧
7 | tags:
8 | - 英语
9 | ---
10 |
11 | # 英语 训练指南 编程篇
12 |
13 | ## 英语 简介
14 |
15 | ### 什么是 英语
16 |
17 | > 英语(English),中文也称英文,是一种西日耳曼语言,诞生于日德兰半岛和莱茵河流域,如今具有全球通用语的地位。
18 | > 由于使用英语的两个主要国家——英国与美国,先后成为世界超级大国之故,并在商业、学术领域具较大影响力,在科技方面的突出贡献和领先地位,而且英文相对易学,因此许多人都将英语做为一种外语或第二语言,把英语作为外国语使用的人约 3-5 亿。英语在香港作为第二官方语言,在欧洲大陆及日本则是最普遍作为外语来学习的语言(32.6%),接着是法语、德语和西班牙语,在中国大陆、澳门特区、台湾、韩国、日本等地,英语是学校的必修外语课程。
19 |
20 | ### 为什么需要使用 英语
21 |
22 | > Language is information and information is everything. —— Killing Eve
23 |
24 | 根据统计,英语是全世界使用人数最多的语言:
25 |
26 | - [List of languages by total number of speakers](https://en.wikipedia.org/wiki/List_of_languages_by_total_number_of_speakers)
27 | - [INTERNET WORLD USERS BY LANGUAGE](https://www.internetworldstats.com/stats7.htm)
28 |
29 | 编程领域最早发展自英语系国家:
30 |
31 | - [计算机早期历史 - Early Computing](https://www.bilibili.com/video/av21376839/)
32 |
33 | 程序的编码是最早来自英语:
34 |
35 | - [Characters, Symbols and the Unicode Miracle - Computerphile](https://www.youtube.com/watch?v=MijmeoH9LT4)
36 |
37 | 编程语言中的很多关键字也来源于英语:
38 |
39 | - [保留字 - MDN](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Lexical_grammar#%E5%85%B3%E9%94%AE%E5%AD%97)
40 |
41 | 代码的编写、命名、注释、文档等,也广泛使用英语:
42 |
43 | - [Learn X in Y minutes](https://learnxinyminutes.com/docs/javascript/)
44 |
45 | 无数编程资料的第一语言都是英语:
46 |
47 | - [GitHub](https://github.com/)
48 | - [Stack Overflow](https://stackoverflow.com/)
49 | - [Web Development - YouTube](https://www.youtube.com/results?search_query=Web+Development)
50 | - [FrontendMasters](https://frontendmasters.com/)
51 | - [Standard ECMA-262](https://www.ecma-international.org/publications/standards/Ecma-262.htm)
52 | - [Daily JS - Medium](https://medium.com/dailyjs)
53 | - [npm](https://www.npmjs.com/)
54 | - [Redux - Doc](https://redux.js.org/)
55 |
56 | 无数非英语母语的大佬,除了母语以外都会英语:
57 |
58 | - Redux 作者、React 团队核心成员:Dan Abramov - **俄国**
59 | - Cycle.js 作者、响应式编程专家:André Staltz - **巴西**
60 | - Linux 之父、Git 之父:Linus Torvalds - **芬兰**
61 |
62 | #### 一定要使用英语?
63 |
64 | 平时更多地使用英语,本质上是提高自己的英语水平,
65 | 使自己能够在第一时间了解最新的资讯。
66 |
67 | 如果不熟悉英语,_只能_ 看汉化版的资料,
68 | 如果还没有汉化版,_只能_ 苦苦等别人汉化,或者看别人二次演绎的文章。
69 | 而汉化、心得这些二手资料的问题在于,可能和原文传达的信息有出入。
70 |
71 | > 对于读者:不要妄图通过二手资料来学习,对于某个有争议的观点,我们应该去寻找最初的参考来源
72 | > —— [怎样理解 Eric Elliott 的文章《为什么说 TypeScript 不适合大型项目》?- justjavac](https://www.zhihu.com/question/338522586/answer/781367678)
73 |
74 | 得不到第一手资料,永远落后于时代,
75 | 永远需要依靠别人,永远没有自己的**核心竞争力**。
76 |
77 | 从更高的视角来看,
78 | 提高自己的英语水平,本质上其实是扩大自己的资讯来源。
79 | 简单的道理:兼听则明,偏信则暗。
80 | 了解学习某个事物,势必需要从大量不同的站点、书籍、文章中获取信息。
81 | 根据英语在技术领域的使用程度之广泛,训练(更多使用)英语**是必须的**。
82 |
83 | #### 一定要只用英语?
84 |
85 | 但作为中文母语者,显然阅读中文还是更有效率的。
86 | 在有**高质量汉化**的情况下(如官方中文文档、视频字幕等),
87 | 也不必特地选择英文版。
88 | 因为对于开发工作来说,学习技术的最终目的是掌握技术,而不是掌握英语。
89 | 如果通过汉化版能够更**高效**地了解学习某个事物,那就是有意义的。
90 | (毕竟汉化本身也算广义的造轮子)
91 |
92 | #### 别的自然语言
93 |
94 | 当然,我还见过使用日语、俄语、德语、法语等编写的资料,
95 | 这些作为第三、第四语言也是可以选择性学习的。
96 | 但以编程领域来说,优先训练自己的英语水平是更合适的。
97 |
98 | ## 学习英语
99 |
100 | ### 概览
101 |
102 | - 耗时:长期(永久)
103 | - 难点:初期陡峭的学习曲线,坚持
104 | - 工具:
105 | - [沙拉查词-聚合词典划词翻译](https://chrome.google.com/webstore/detail/%E6%B2%99%E6%8B%89%E6%9F%A5%E8%AF%8D-%E8%81%9A%E5%90%88%E8%AF%8D%E5%85%B8%E5%88%92%E8%AF%8D%E7%BF%BB%E8%AF%91/cdonnmffkdaoajfknoeeecmchibpmkmg)
106 | - [Grammarly for Chrome](https://chrome.google.com/webstore/detail/grammarly-for-chrome/kbfnbcaeplbcioakkpcpgfkobkghlhen)
107 |
108 | ### 学习路线
109 |
110 | 两个简单的道理:
111 |
112 | - 工欲善其事,必先利其器
113 | - 用进废退、熟能生巧
114 |
115 | 我的做法**不是**先**背**一本《计算机英语》,
116 | 而**是立即开始持续使用**英语,
117 | 直到能够全面覆盖每天工作流程。
118 | (艾宾浩斯遗忘曲线?不存在的,天天用,哪来的遗忘)
119 |
120 | - 打造使用环境
121 | - 把系统调成英文
122 | - 准备好翻译器和插件
123 | - 学习技术时
124 | - 优先选择英文的教程
125 | - 尽量看文档的英文版本
126 | - 多看英文技术文章
127 | - 写代码时
128 | - 更有意义的英语变量命名
129 | - 尝试写英语注释
130 | - 用 Google 进行搜索(或 Bing、DuckDuckGo 等,反正不是百度)
131 | - 用英语关键字搜索资料
132 | - 创造更多使用场景
133 | - 参与 GitHub 的开源项目
134 | - 和老外沟通
135 | - 给没有中文的技术文档提供翻译
136 | - 做自己的开源项目,尝试用英语写文档
137 |
138 | 以上列表覆盖“听说读写”中的绝大部分部分(除“说”外),
139 | 创造了良好的使用环境,熟练使用英语的也就是自然而然的事情了。
140 |
141 | ## 资料
142 |
143 | - 工具
144 | - [沙拉查词-聚合词典划词翻译](https://chrome.google.com/webstore/detail/%E6%B2%99%E6%8B%89%E6%9F%A5%E8%AF%8D-%E8%81%9A%E5%90%88%E8%AF%8D%E5%85%B8%E5%88%92%E8%AF%8D%E7%BF%BB%E8%AF%91/cdonnmffkdaoajfknoeeecmchibpmkmg)
145 | - [Grammarly for Chrome](https://chrome.google.com/webstore/detail/grammarly-for-chrome/kbfnbcaeplbcioakkpcpgfkobkghlhen)
146 | - 扩展阅读
147 | - [English-level-up-tips-for-Chinese](https://github.com/byoungd/english-level-up-tips-for-Chinese)
148 | - [人人都能用英语](https://github.com/xiaolai/everyone-can-use-english)
149 | - [词汇量 2 万? 纯正英式? 中国人的英语误区 (亚洲适用)](https://www.youtube.com/watch?v=xmIB-kyFeg8)
150 |
--------------------------------------------------------------------------------
/docs/note/00.resources/the-digital-productivity-pyramid.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seognil/fe-foundation/74290e0ec2a3f0d8cea2c719c6e1dd21a3c2fbb0/docs/note/00.resources/the-digital-productivity-pyramid.jpeg
--------------------------------------------------------------------------------
/docs/note/02.workspace/0.mac.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Mac 环境(M1 + Monterey)
3 | date: 2021-11-15 15:43:26
4 | permalink: /workspace/mac
5 | categories:
6 | - 开发环境
7 | tags:
8 | - mac
9 | - 工具
10 | ---
11 |
12 | # Mac 环境(M1 + Monterey)
13 |
14 | ## Mac 简介
15 |
16 | - 视频
17 | - [学生党 M1 Mac 入门指北](https://www.bilibili.com/video/BV1sD4y1X7MQ)
18 | - [Mac Tutorial for Beginners - Switching from Windows to macOS](https://www.youtube.com/watch?v=67keaaWOKzE)
19 | - [How to Set Up Your Mac for Maximum Productivity](https://www.youtube.com/watch?v=XBi3OB23Utk)
20 | - 官方文档
21 | - [macOS 使用手册](https://support.apple.com/zh-cn/guide/mac-help/welcome/mac)
22 | - [Mac 键盘快捷键](https://support.apple.com/zh-cn/HT201236)
23 | - M1 兼容性相关
24 | - [Is Apple Silicon ready?](https://isapplesiliconready.com/)
25 | - [Does It ARM?](https://doesitarm.com/)
26 |
27 | ## 配置
28 |
29 | (如果有其他 Mac 的话用 Time Machine 直接迁移就好)
30 |
31 | ### Time Machine 恢复后的问题
32 |
33 | #### 如果网络不正常
34 |
35 | - 刚配好丝丝要重启
36 | - 到这里看看删掉与 network 相关的文件,重启:
37 |
38 | ```sh
39 | open /Library/Preferences/SystemConfiguration
40 | ```
41 |
42 | ```sh
43 | # 找到这些文件
44 | com.apple.airport.preferences.plist
45 | com.apple.network.eapolclient.configuration.plist
46 | com.apple.wifi.message-tracer.plist
47 | NetworkInterfaces.plist
48 | preferences.plist
49 | ```
50 |
51 | #### 如果是恢复到另一台设备
52 |
53 | - 到 Sharing 改电脑名字,重启
54 | - Chrome 用一个新账户重新同步(不然似乎历史记录会识别为同一台设备)
55 |
56 | ### System Preferences
57 |
58 | - Language & Region:英语、简体中文
59 | - Sharing:改电脑名字,重启
60 | - Software Update
61 | - Keyboard:先把 Key Repeat 和 Delay 调到最快
62 |
63 | 安装 [Additional Tools for Xcode](https://developer.apple.com/download/more/?=additional%20tools) 里的 [Network Link Conditioner](https://nshipster.com/network-link-conditioner/)(给电脑限速用的)
64 |
65 | (如果装 NTFS 工具等需要 [Reduced Security](https://support.apple.com/en-gb/guide/mac-help/mchl768f7291/mac))
66 |
67 | ### dotfiles
68 |
69 | ```sh
70 | .zprofile
71 | .zshrc
72 | .zsh_history
73 | .nrmrc
74 | ```
75 |
76 | ### 终端配置
77 |
78 | sudo 无需密码:
79 |
80 | ```sh
81 | echo -e "\n$USER ALL=(ALL) NOPASSWD: ALL" | sudo tee -a /etc/sudoers
82 | ```
83 |
84 | 允许安装运行任意软件:
85 |
86 | ```sh
87 | sudo spctl --global-disable
88 | sudo spctl --status
89 | ```
90 |
91 | bin 目录权限(解决 npm global install 问题):
92 |
93 | ```sh
94 | sudo chown -R $USER /usr/local/bin
95 | ```
96 |
97 | 复制来的 ssh 私钥要调成只读:
98 |
99 | ```sh
100 | sudo chmod 600
101 | ```
102 |
103 | 禁止 PressAndHold(需重启)(解决 [这个 VS Code 问题](https://github.com/microsoft/vscode/issues/31919)):
104 |
105 | ```sh
106 | defaults write -g ApplePressAndHoldEnabled -bool false
107 | ```
108 |
109 | 更快的按键重复(控制面板的 KeyRepeat 最快才到 2)(需重启):
110 |
111 | ```sh
112 | defaults write -g InitialKeyRepeat -int 15
113 | defaults write -g KeyRepeat -int 1
114 | ```
115 |
116 | 提高 Time Machine 的速度(重启后失效,可以做一个 function):
117 |
118 | ```sh
119 | sudo sysctl debug.lowpri_throttle_enabled=0
120 | ```
121 |
122 | 启用 `locate` 命令并建立索引:
123 |
124 | ```sh
125 | sudo launchctl load -w /System/Library/LaunchDaemons/com.apple.locate.plist
126 | ```
127 |
128 | ### 安装基本工具
129 |
130 | 魔法丝袜之影(略)
131 |
132 | ```sh
133 | export ALL_PROXY='http://127.0.0.1:1080'
134 | ```
135 |
136 | 安装 Xcode Command Line Tools:
137 |
138 | ```sh
139 | xcode-select --install
140 | ```
141 |
142 | 安装 [Brew](https://brew.sh/):
143 |
144 | ```sh
145 | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
146 | ```
147 |
148 | (按照提示)激活 `brew` 命令:
149 |
150 | ```sh
151 | echo 'eval $(/opt/homebrew/bin/brew shellenv)' >> $HOME/.zprofile
152 | eval "$(/opt/homebrew/bin/brew shellenv)"
153 | ```
154 |
155 | 安装一些基本工具(虽然系统自带一些,但是用 brew 来做后续更新):
156 |
157 | ```sh
158 | brew install --formula bat git n scc tig trash tree zsh
159 | brew install --cask google-chrome visual-studio-code iterm2
160 | ```
161 |
162 | 安装 [Oh My Zsh](https://github.com/ohmyzsh/ohmyzsh):
163 |
164 | ```sh
165 | sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
166 | ```
167 |
168 | 安装 [更纱黑体](https://github.com/be5invis/Sarasa-Gothic)(`"Sarasa Mono SC"`, "Sarasa Term SC"):
169 |
170 | ```sh
171 | brew tap homebrew/cask-fonts
172 | brew install font-sarasa-gothic
173 | ```
174 |
175 | 安装 Node.js(我用 n 来管理):
176 |
177 | ```sh
178 | sudo n 16
179 | ```
180 |
181 | ### Finder
182 |
183 | - 显示扩展名:`cmd + ,` > Advanced
184 | - (剪切功能的快捷键:`cmd + option + v`)
185 |
186 | 总是显示隐藏文件:
187 |
188 | ```sh
189 | defaults write com.apple.finder AppleShowAllFiles -boolean true; killall Finder
190 | ```
191 |
192 | 标题显示完整路径:
193 |
194 | ```sh
195 | defaults write com.apple.finder \_FXShowPosixPathInTitle -bool true; killall Finder
196 | ```
197 |
198 | Open In Terminal,(装好到 System Preferences > Extensions 开启):
199 |
200 | ```sh
201 | brew install openinterminal
202 | ```
203 |
204 | (其他配置略,`cmd + ,`、`cmd + j`)
205 |
206 | ## 其他安装的工具
207 |
208 | ### npm global
209 |
210 | `npm -g i`
211 |
212 | - [pnpm](https://github.com/pnpm/pnpm):代替 npm 用
213 | - [@antfu/ni](https://github.com/antfu/ni):自动判断当前的包管理器(npm、yarn、pnpm)
214 | - [@types/node](https://www.npmjs.com/package/@types/node):node 的类型定义,写 ts 脚本的时候辅助用
215 | - [serve](https://github.com/vercel/serve):读本地文件夹起一个 server(类似 http-server)
216 | - [tldr](https://github.com/tldr-pages/tldr):简化的 help 工具(类似 man 或 --help)
217 | - [tsno](https://github.com/egoist/tsno):更方便的 ts-node 的代替品,底层是 esbuild
218 | - [vercel](https://github.com/vercel/vercel):部署本地 app dist 到 vercel
219 |
220 | 把全局安装的 `@types` 软链接到根目录,[以便 ts 全局搜索](https://www.typescriptlang.org/tsconfig#typeRoots)
221 |
222 | ```sh
223 | mkdir -p ~/node_modules/
224 | ln -s ~/pnpm-global/5/node_modules/@types ~/node_modules/@types
225 | ```
226 |
227 | ### brew
228 |
229 | `brew install`
230 |
231 | - [bat](https://github.com/sharkdp/bat):显示文件内容(类似 cat)
232 | - [n](https://github.com/tj/n):Node 版本管理器
233 | - [neofetch](https://github.com/dylanaraps/neofetch):显示当前环境信息(类似 screenfetch)
234 | - [pngquant](https://pngquant.org/):png 图片压缩
235 | - [scc](https://github.com/boyter/scc):统计代码行数(类似 cloc)
236 | - [smartmontools](https://apple.stackexchange.com/questions/135565/how-do-i-get-detailed-smart-disk-information-on-os-x-mavericks-or-later):磁盘健康度
237 | - [tig](https://jonas.github.io/tig/doc/manual.html):更方便的 git history
238 | - [trash](https://hasseg.org/trash/):扔到垃圾桶(用来代替 `rm -rf`)
239 | - [tree](https://sourabhbajaj.com/mac-setup/iTerm/tree.html):显示文件夹树状结构
240 | - [you-get](https://github.com/soimort/you-get):视频下载器
241 |
242 | ### brew cask
243 |
244 | `brew install --cask`
245 |
246 | - 开发相关
247 | - [docker](https://www.docker.com/):轻量级虚拟化技术
248 | - [switchhosts](https://github.com/oldj/SwitchHosts):Host 编辑器
249 | - [postman](https://www.getpostman.com/):网络请求监听
250 | - 系统增强
251 | - [alfred](https://www.alfredapp.com/):增强版 spotlight
252 | - [bettertouchtool](https://folivora.ai/):快捷键绑定
253 | - [hiddenbar](https://github.com/dwarvesf/hidden):菜单栏图标折叠
254 | - [karabiner-elements](https://karabiner-elements.pqrs.org/):键位映射
255 | - [monitorcontrol](https://github.com/MonitorControl/MonitorControl):通过软件直接控制外接显示器硬件亮度
256 | - [openinterminal](https://github.com/Ji4n1ng/OpenInTerminal):Finder 打开到终端
257 | - [unshaky](https://github.com/aahung/Unshaky):防止按键误触发的工具(解决蝴蝶键盘问题)
258 | - 性能和监控
259 | - [cinebench](https://www.maxon.net/en/products/cinebench-r20-overview/):CPU/GPU 性能测试
260 | - [coconutbattery](https://coconut-flavour.com/coconutbattery/):电池健康度检查
261 | - [daisydisk](https://daisydiskapp.com/):磁盘空间分析
262 | - [istat-menus](https://bjango.com/mac/istatmenus/):任务栏硬件监控
263 | - 其他日用
264 | - [fliqlo](https://fliqlo.com/):一个翻页时钟屏保
265 | - [keka](https://www.keka.io/):压缩软件
266 | - [keycastr](https://github.com/keycastr/keycastr):显示按键(录屏时用)
267 | - [iina](https://iina.io/):视频播放器
268 | - [itsycal](https://www.mowglii.com/itsycal/):菜单栏日历
269 | - [imazing](https://imazing.com/):备份 iPhone 的软件
270 | - [telegram-desktop](https://desktop.telegram.org/):Telegram 桌面客户端
271 | - 网盘/下载
272 | - [onedrive](https://onedrive.live.com/):One Drive
273 | - [megasync](https://mega.nz/sync):Mega Sync,可以排除 node_modules,放一些临时项目用
274 | - [thunder](https://mac.xunlei.com/):迅雷
275 |
276 | ### App store
277 |
278 | - [Blackmagic Disk Speed Test](https://apps.apple.com/us/app/blackmagic-disk-speed-test/id425264550):磁盘速度测试
279 | - [Desktop Clock](https://apps.apple.com/us/app/desktop-clock-live/id894760156?mt=12):桌面时钟
280 | - [GIPHY CAPTURE](https://giphy.com/apps/giphycapture):截动图/视频工具
281 | - [OneNote](https://www.onenote.com/):微软的跨平台笔记
282 | - [QQ](https://im.qq.com/):QQ
283 | - [Unsplash Wallpapers](https://apps.apple.com/us/app/unsplash-wallpapers/id1284863847?mt=12):Unsplash 随机壁纸
284 | - [WeChat](https://mac.weixin.qq.com/):微信
285 | - [Xcode](https://developer.apple.com/xcode/):苹果自家的 IDE
286 | - [Xnip](https://xnipapp.com/):截图工具
287 |
--------------------------------------------------------------------------------
/docs/note/02.workspace/1.chrome.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 关于 Chrome
3 | date: 2019-12-14 22:03:19
4 | permalink: /workspace/chrome
5 | categories:
6 | - 开发环境
7 | tags:
8 | - 浏览器
9 | - chrome
10 | ---
11 |
12 | # 关于 Chrome
13 |
14 | ## Chrome 简介
15 |
16 | [Chrome](https://www.google.com/chrome/) 是一个免费的跨平台浏览器,由 Google 开发,
17 | Chrome 对于前端开发来说(尤其是调试代码)非常方便,
18 | 并且有丰富的插件市场,包括很多前端框架的调试插件。
19 |
20 | 用 Brew 安装 Chrome:`brew cask install google-chrome`
21 |
22 | ### Chrome 界面设计
23 |
24 | - [Redesigning Chrome Desktop: The value of a pixel](https://medium.com/google-design/redesigning-chrome-desktop-769aeb5ab987)
25 | - [Unboxing Chrome: Redesigning the omnibox](https://medium.com/@san_toki/unboxing-chrome-f6af7b8161a2)
26 |
27 | ## 浏览器的知识
28 |
29 | ### 浏览器基本调试技巧
30 |
31 | - [在 Chrome DevTools 中调试 JavaScript 入门](https://developers.google.com/web/tools/chrome-devtools/javascript/?hl=zh-cn)
32 | - [Performance Analysis Reference](https://developers.google.com/web/tools/chrome-devtools/evaluate-performance/reference?hl=zh-cn)
33 |
34 | ### 浏览器原理
35 |
36 | - [当···时发生了什么?](https://github.com/skyline75489/what-happens-when-zh_CN)
37 | - [浏览器输入 URL 后发生了什么?](https://zhuanlan.zhihu.com/p/43369093)
38 | - [Navigation Timing Level 2](https://w3c.github.io/navigation-timing/)
39 |
40 | * [浏览器的工作原理:新式网络浏览器幕后揭秘](https://www.html5rocks.com/zh/tutorials/internals/howbrowserswork/)
41 |
42 | - [[译] 现代浏览器内部揭秘(第一部分)](https://juejin.im/post/5b9b0932e51d450e9059c16a)
43 | - [[译] 现代浏览器内部揭秘(第二部分)](https://juejin.im/post/5bc293cf6fb9a05ce95c8468)
44 | - [[译] 现代浏览器内部揭秘(第三部分)](https://juejin.im/post/5bc29d56e51d450e9e4466cc)
45 | - [[译] 现代浏览器内部揭秘(第四部分)](https://juejin.im/post/5bc95247e51d450e40072e49)
46 |
47 | ## 设置 Chrome
48 |
49 | ### 浏览器设置
50 |
51 | - 确认搜索引擎设置为 Google (或 bing、DuckDuckGo,反正不要用百度)
52 | - 开启账号同步
53 |
54 | ### 插件
55 |
56 | 我用的一些重要插件:
57 |
58 | #### 私人
59 |
60 | - [Google Keep](https://keep.google.com/):笔记速写工具
61 | - [LastPass](https://chrome.google.com/webstore/detail/lastpass-free-password-ma/hdokiejnpimakedhajhdlcegeplioahd):密码管理工具
62 | - [Adblock Plus](https://chrome.google.com/webstore/detail/adblock-plus-free-ad-bloc/cfhdojbkjhnklbpkdaibdccddilifddb):广告屏蔽
63 | - [Momentum](https://chrome.google.com/webstore/detail/momentum/laookkfknpbbblfpciffpaejjkokdgca):个性化新标签页
64 | - [PocketTube: Youtube Subscription Manager](https://chrome.google.com/webstore/detail/pockettube-youtube-subscr/kdmnjgijlmjgmimahnillepgcgeemffb):YouTube 订阅管理器
65 |
66 | #### 干活
67 |
68 | - 杂项
69 | - [Proxy SwitchyOmega](https://chrome.google.com/webstore/detail/proxy-switchyomega/padekgcemlokbadohgkifijomclgjgif):Proxy 管理工具
70 | - [Workona](https://chrome.google.com/webstore/detail/workona/ailcmbgekjpnablpdkmaaccecekgdhlh?hl=en):工作区管理器(增强的标签管理器)
71 | - ~~[Tab Manager Plus for Chrome](https://chrome.google.com/webstore/detail/tab-manager-plus-for-chro/cnkdjjdmfiffagllbiiilooaoofcoeff):标签管理器~~
72 | - [Tampermonkey](https://chrome.google.com/webstore/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo):脚本扩展平台
73 | - [Stylus](https://chrome.google.com/webstore/detail/stylus/clngdbkpkpeebahjckkjfobafhncgmne):网站样式扩展平台
74 | - 英语
75 | - [沙拉查词-聚合词典划词翻译](https://chrome.google.com/webstore/detail/%E6%B2%99%E6%8B%89%E6%9F%A5%E8%AF%8D-%E8%81%9A%E5%90%88%E8%AF%8D%E5%85%B8%E5%88%92%E8%AF%8D%E7%BF%BB%E8%AF%91/cdonnmffkdaoajfknoeeecmchibpmkmg):划词翻译(参考 [英语 训练指南](/study/using-english))
76 | - [Grammarly for Chrome](https://chrome.google.com/webstore/detail/grammarly-for-chrome/kbfnbcaeplbcioakkpcpgfkobkghlhen):英语语法检查助手
77 | - 增强
78 | - [Video Speed Controller](https://chrome.google.com/webstore/detail/video-speed-controller/nffaoalbilbmmfgbnbgppjihopabppdk):视频快捷键(参考 [用快捷键控制视频播放](/workspace/my-video-player-shortcuts))
79 | - [User JavaScript and CSS](https://chrome.google.com/webstore/detail/user-javascript-and-css/nbhcbdghjpllgmfilhnhkllmkecfmpld):自定义脚本和样式注入
80 | - [JSON Viewer](https://chrome.google.com/webstore/detail/json-viewer/gbmdgpbipfallnflgajpaliibnhdgobh):JSON 格式化查看器
81 | - Github
82 | - [Enhanced Github](https://chrome.google.com/webstore/detail/enhanced-github/anlikcnbgdeidpacdbdljnabclhahhmd?hl=en):GitHub 功能增强
83 | - [Isometric Contributions](https://chrome.google.com/webstore/detail/isometric-contributions/mjoedlfflcchnleknnceiplgaeoegien):GitHub 提交活动 3D 化
84 | - [Octotree](https://chrome.google.com/webstore/detail/octotree/bkhaagjahfmjljalopjnoealnfndnagc):Repo 侧边栏文件树
85 | - 开发
86 | - [Console Importer](https://chrome.google.com/webstore/detail/console-importer/hgajpakhafplebkdljleajgbpdmplhie):在控制台安装 npm 包
87 | - [React Developer Tools](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi):React DevTools
88 | - [Redux DevTools](https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd):Redux DevTools
89 | - [Vue.js devtools](https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd):Vue DevTools
90 | - [MobX Developer Tools](https://chrome.google.com/webstore/detail/mobx-developer-tools/pfgnfdagidkfgccljigdamigbcnndkod):MobX DevTools
91 |
--------------------------------------------------------------------------------
/docs/note/02.workspace/2.vscode.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 关于 VS Code
3 | date: 2019-12-14 22:03:19
4 | permalink: /workspace/vscode
5 | categories:
6 | - 开发环境
7 | tags:
8 | - vscode
9 | - 工具
10 | ---
11 |
12 | # 关于 VS Code
13 |
14 | ## VS Code 简介
15 |
16 | [VS Code](https://code.visualstudio.com/) 是一个跨平台代码编辑器,由微软开发并开源,
17 | VS Code 兼顾了轻便性和扩展性,是前端开发(甚至其他语言)的主流编辑器。
18 | (另一些编辑器/IDE,例如:WebStorm、Sublime Text 等)
19 |
20 | 用 Brew 安装 VS Code:`brew cask install visual-studio-code`
21 |
22 | 安装完成后,可以 [注册 `code` 命令](https://code.visualstudio.com/docs/setup/mac#_launching-from-the-command-line),
23 | 使得在命令行中执行 `code ./project1` 即可用 VS Code 打开项目或文件。
24 |
25 | ### VS Code 基本功能
26 |
27 | - 命令行
28 | - [注册 `code` 命令](https://code.visualstudio.com/docs/setup/mac#_launching-from-the-command-line)
29 | - 功能系统
30 | - [命令面板](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette)
31 | - [插件系统](https://code.visualstudio.com/docs/editor/extension-gallery)
32 | - [内建终端](https://code.visualstudio.com/docs/editor/integrated-terminal)
33 | - [内建 Git](https://code.visualstudio.com/Docs/editor/versioncontrol#_git-support)
34 | - [snippets](https://code.visualstudio.com/docs/editor/userdefinedsnippets)
35 | - [settings](https://code.visualstudio.com/docs/getstarted/settings)
36 | - 增强功能
37 | - [intellisense](https://code.visualstudio.com/docs/editor/intellisense)
38 | - [定义跳转](https://code.visualstudio.com/Docs/editor/editingevolved#_peek)
39 | - [全局重命名](https://code.visualstudio.com/Docs/editor/editingevolved#_rename-symbol)
40 | - [代码格式化](https://code.visualstudio.com/docs/editor/codebasics#_formatting)
41 | - 开发
42 | - [Debugger](https://code.visualstudio.com/Docs/editor/debugging)
43 | - [快捷键](https://code.visualstudio.com/docs/getstarted/keybindings#_keyboard-shortcuts-reference)(Mac)
44 | - cmd + p、cmd + shift + p
45 | - cmd + f、cmd + shift + f
46 | - cmd + d、cmd + shift + L
47 | - opt + shift + o:organize imports
48 |
49 | ### VS Code 源码
50 |
51 | - [从 VSCode 看大型 IDE 技术架构](https://zhuanlan.zhihu.com/p/96041706)
52 |
53 | ## 使用 VS Code
54 |
55 | ### 入门
56 |
57 | - [VS Code Top-Ten Pro Tips](https://www.youtube.com/watch?v=u21W_tfPVrY)
58 | 10 分钟:10 个 VS Code 常用功能一览
59 | - [Visual Studio Code Intro & Setup](https://www.youtube.com/watch?v=fnPhJHN0jTE)
60 | 40 分钟:(2017 年的视频,有些功能现在可能改变,但总体是相似的)
61 | VS Code 界面功能和配置,基本使用,一些插件介绍,Git 简介
62 | - [Visual Studio Code Can Do That: Tips & Tricks : Build 2018](https://www.youtube.com/watch?v=OOG3xcUQY5k)
63 | 80 分钟:
64 |
65 | - [25 VS Code Productivity Tips and Speed Hacks](https://www.youtube.com/watch?v=ifTF3ags0XI)
66 |
67 | ### 插件
68 |
69 | 我用的一些重要插件:
70 |
71 | - 功能增强
72 | - [Settings Sync](https://marketplace.visualstudio.com/items?itemName=Shan.code-settings-sync):同步所有配置到 Git Gist
73 | - [GitLens — Git supercharged](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens):Git 增强
74 | - [Code Runner](https://marketplace.visualstudio.com/items?itemName=formulahendry.code-runner):快捷键直接运行代码文件
75 | - [Diff Tool](https://marketplace.visualstudio.com/items?itemName=jinsihou.diff-tool):Diff 两个文件
76 | - [Code Outline](https://marketplace.visualstudio.com/items?itemName=patrys.vscode-code-outline):显示代码大致结构
77 | - [Quokka.js](https://marketplace.visualstudio.com/items?itemName=WallabyJs.quokka-vscode):直接显示代码运行结果
78 | - [LeetCode](https://marketplace.visualstudio.com/items?itemName=shengchen.vscode-leetcode):在本地刷 LeetCode
79 | - [open in browser](https://marketplace.visualstudio.com/items?itemName=techer.open-in-browser):用浏览器打开文件
80 | - 界面增强
81 | - [Dracula](https://draculatheme.com/):高亮主题
82 | - [Material Icon Theme](https://marketplace.visualstudio.com/items?itemName=PKief.material-icon-theme):图标主题
83 | - [Better Comments](https://marketplace.visualstudio.com/items?itemName=aaron-bond.better-comments):不同颜色标记不同类型的注释
84 | - [Todo Tree](https://marketplace.visualstudio.com/items?itemName=Gruntfuggly.todo-tree):高亮显示 TODO
85 | - [Bracket Pair Colorizer](https://marketplace.visualstudio.com/items?itemName=CoenraadS.bracket-pair-colorizer):用不同颜色配对不同层级的括号
86 | - [indent-rainbow](https://marketplace.visualstudio.com/items?itemName=oderwat.indent-rainbow):彩虹色缩进
87 | - [Import Cost](https://marketplace.visualstudio.com/items?itemName=wix.vscode-import-cost):显示包的 import 大小
88 | - [filesize](https://marketplace.visualstudio.com/items?itemName=mkxml.vscode-filesize):显示文件大小
89 | - 自动化
90 |
91 | - [Path Intellisense](https://marketplace.visualstudio.com/items?itemName=christian-kohler.path-intellisense):路径自动补全
92 | - [npm Intellisense](https://marketplace.visualstudio.com/items?itemName=christian-kohler.npm-intellisense):包名自动补全
93 | - [Visual Studio IntelliCode](https://marketplace.visualstudio.com/items?itemName=VisualStudioExptTeam.vscodeintellicode):代码自动补全(AI-based)
94 | - [Prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode):格式化
95 | - [ESLint](https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint):静态检查
96 | - [Sort lines](https://marketplace.visualstudio.com/items?itemName=Tyriar.sort-lines):多行字典排序
97 | - [Markdown All in One](https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one):Markdown 增强(参考 [Markdown 学习指南](/cs/markdown))
98 | - HTML/JSX
99 | - [Auto Close Tag](https://marketplace.visualstudio.com/items?itemName=formulahendry.auto-close-tag):自动闭合标签
100 | - [Auto Rename Tag](https://marketplace.visualstudio.com/items?itemName=formulahendry.auto-rename-tag):自动重命名标签(同步开头结尾)
101 | - CSS
102 | - 无
103 | - JS
104 | - 无
105 | - React
106 | - [ES7 React/Redux/GraphQL/React-Native snippets](https://marketplace.visualstudio.com/items?itemName=dsznajder.es7-react-js-snippets):React 开发插件集
107 | - Vue
108 | - [Vue.js Extension Pack](https://marketplace.visualstudio.com/items?itemName=mubaidr.vuejs-extension-pack):Vue 开发插件集
109 | - [Vue 2 Snippets](https://marketplace.visualstudio.com/items?itemName=hollowtree.vue-snippets):Vue 代码片段
110 |
--------------------------------------------------------------------------------
/docs/note/08.misc/clean-a-keyboard.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 如何清洁机械键盘
3 | date: 2019-11-08 16:07:45
4 | permalink: /misc/clean-a-keyboard
5 | categories:
6 | - 杂项
7 | tags:
8 | - 杂谈
9 | ---
10 |
11 | # 如何清洁机械键盘
12 |
13 | ## 这都要写?
14 |
15 | 嗯…当我拆干净之后发现缺少趁手的工具,留着那么多垃圾再装回去有点难以接受……
16 | 但是因为缺少合适的工具,导致整个过程很没有效率,最后也没达到最好的清洁效果。
17 |
18 | ## 总览
19 |
20 | - 耗时:根据工具和方法,大约需要 1~2 小时
21 | - 难度:中(迫真)
22 | - 准备:
23 | - 三角拆机片
24 | - 拔键器
25 | - 酒精棉片
26 | - 十字螺丝刀
27 | - 一字螺丝刀 (或任意够硬的细金属棒)
28 | - 毛刷(旧牙刷)
29 | - 脸盆(可选)
30 | - 内衣网兜+洗衣机(可选)
31 | - 润滑油(可选 缝纫机的那种?)
32 |
33 | ## 过程
34 |
35 | (图忘拍了,以后有机会再补充)
36 |
37 | (酒精是脂溶性的,酒精棉片的作用在于可以有效清除油性物质,确保你的设备本身不会和它发生反应)
38 |
39 | - 在拆之前最好拍一下按键布局(确信)
40 |
41 | * 清洁外壳(如果你想的话)
42 | - 用**拆机片**拆出键盘外壳
43 | - (有的键盘是卡扣式设计的)
44 | - 或用**螺丝刀**拧下外壳(螺丝可能藏在脚垫里)
45 | - 手动水洗或干洗
46 |
47 | - 清洁键帽
48 | - 用**拔键器**拔除所有键帽
49 | - 清洁键帽(方法 N 选 1)
50 | - 把所有键帽装到**内衣网兜**里,扔到**洗衣机**里(洗得巨干净,记得别加烘干步骤防止变形)
51 | - 放**脸盆**里用刷子手动水洗
52 | - 用**酒精棉片**手动干洗
53 |
54 | * 清洁面板
55 | - 手持面板(轴体朝下,防止垃圾屑掉落到轴里)
56 | - 用**毛刷**清洁轴体周围的 PCB(或有钢板)部分
57 | - (因为这样比较经济实惠)
58 | - 用**酒精棉片**进一步清洁
59 | - (有可能会有油脂毛发等顽固污渍)
60 |
61 | - 金属连杆(说明)
62 | - 有的键盘可能会有连杆设计(比如空格那种长键下面会有)
63 | - 拆之前记录部件的安装方式(方向)
64 | - 金属连杆
65 | - 拆除所有相关部件
66 | - 连杆一般都是卡扣式固定在板上,用**一字螺丝刀**从关键部位顶出来
67 | - 都是小部件,可以选择用**酒精棉片**清洁
68 | - 把连杆按照正确的安装方式和键帽组合
69 | - 完毕后可以选择性给关节部位涂上**润滑油**
70 | - 把键帽直接装回面板上
71 | - 用**一字螺丝刀**将连杆的固定位置顶回卡扣中
72 |
73 | * 收尾
74 | - 将所有部分按照正确的方式组装回去
75 | - (清理工作台)
76 | - (测试一下按键可靠性(随便找个在线的 比如 ))
77 | - (拍照发朋友圈假装是个新键盘)
78 |
--------------------------------------------------------------------------------
/docs/note/08.misc/linux-basic-security.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Ubuntu 服务器基本防护
3 | date: 2019-11-10 21:57:03
4 | permalink: /misc/linux-basic-security
5 | categories:
6 | - 杂项
7 | tags:
8 | - 杂谈
9 | ---
10 |
11 | # Ubuntu 服务器基本防护
12 |
13 | 记录一下步骤
14 |
15 | - 加一个新用户
16 | - 禁用 root 登录
17 | - 禁用密码登录(只允许 rsa)
18 | - 修改 ssh 端口
19 | - 防火墙
20 |
21 | ## 用户
22 |
23 | ```bash
24 | # * 加用户
25 | sudo adduser USERNAME
26 | # * 加到 root 组
27 | sudo usermod -aG sudo USERNAME
28 |
29 | # * 删除用户(可能要先 kill 该用户进程)
30 | # ps -aux | grep USERNAME
31 | # sudo pkill -u USERNAME
32 | sudo deluser USERNAME
33 | sudo groupdel GROUPNAME
34 |
35 | # * 查看用户和组
36 | cat /etc/passwd
37 | cat /etc/group
38 |
39 | # * 修改密码,ubuntu 初始 root 无密码
40 | sudo su root
41 | sudo passwd root
42 |
43 | # * sudo 免密
44 | echo -e "\n USERNAME ALL=(ALL) NOPASSWD: ALL" | sudo tee -a /etc/sudoers
45 |
46 | # * 加 shh key (在 host 操作 需要在关闭密码登录前操作)
47 | ssh-copy-id -i ~/LOCALKEY.public USER@HOST
48 |
49 | # * ssh 认证文件位置 每条 append
50 | # /root/.ssh/authorized_keys
51 | # /home/USERNAME/.ssh/authorized_keys
52 |
53 | # * change user
54 | su
55 | ```
56 |
57 | ## ssh 配置
58 |
59 | ```bash
60 | # * check
61 | # sudo vi /etc/ssh/sshd_config
62 |
63 | # * tweak config
64 | sudo sed -i 's/^.*\bPort\b.*$/Port 0000/' /etc/ssh/sshd_config
65 | sudo sed -i 's/^.*PasswordAuthentication.*$/PasswordAuthentication no/' /etc/ssh/sshd_config
66 | # sudo sed -i 's/^.*PasswordAuthentication.*$/PasswordAuthentication yes/' /etc/ssh/sshd_config
67 |
68 | # * default is 'prohibit-password', so its not necessery
69 | sudo sed -i 's/^.*PermitRootLogin.*$/PermitRootLogin no/' /etc/ssh/sshd_config
70 | # sudo sed -i 's/^.*PermitRootLogin.*$/PermitRootLogin yes/' /etc/ssh/sshd_config
71 | # sudo sed -i 's/^.*PermitRootLogin.*$/#PermitRootLogin prohibit-password/' /etc/ssh/sshd_config
72 |
73 | # * 重启服务
74 | sudo service sshd restart
75 | # sudo systemctl restart sshd
76 | ```
77 |
78 | ## ufw 防火墙
79 |
80 | ```bash
81 | # * 拒绝所有,打开指定
82 |
83 | sudo ufw default deny incoming
84 |
85 | # sudo ufw allow ssh
86 | sudo ufw allow 0000
87 | sudo ufw allow from 0.0.0.0 to any port 0000 proto tcp
88 |
89 | # * 禁止 ping
90 | sudo copy /etc/ufw/before.rules /etc/ufw/before.rules.bak
91 | sudo sed -ir 's/\(ufw-before-input -p icmp --icmp-type.*\) .*/\1 DROP/' /etc/ufw/before.rules
92 | # sudo sed -ir 's/\(ufw-before-input -p icmp --icmp-type.*\) .*/\1 ACCEPT/' /etc/ufw/before.rules
93 |
94 | # * 直接改了配置文件需要重启 ufw
95 | sudo ufw reload
96 | ```
97 |
98 | ## 系统
99 |
100 | ```bash
101 | # * 设置主机名
102 | hostnamectl set-hostname example.com
103 |
104 | # * 查看 shell
105 | echo $SHELL
106 | cat /etc/shells
107 |
108 | # * 查看系统信息
109 | cat /etc/*-release
110 | ```
111 |
112 | ## 其他命令
113 |
114 | ```bash
115 |
116 | # * 生成秘钥
117 | ssh-keygen -t rsa -b 4096 -f ~/folder/id_rsa
118 |
119 | # * 端口转发
120 | ssh -LN localhost:2000:theirlocalhost:80 root@0.0.0.0 -p 0000
121 |
122 | # * 清除某个 known_hosts
123 | ssh-keygen -R HOSTNAME
124 |
125 | # * proxy
126 | export http_proxy=http://
127 | export https_proxy=http://
128 | ```
129 |
--------------------------------------------------------------------------------
/docs/note/08.misc/my-video-player-shortcuts.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 用快捷键控制视频播放
3 | date: 2019-12-14 22:03:19
4 | permalink: /workspace/my-video-player-shortcuts
5 | categories:
6 | - 开发环境
7 | tags:
8 | - 脚本
9 | ---
10 |
11 | # 用快捷键控制视频播放
12 |
13 | 如果你有通过视频学习的经历,
14 | 你应该知道快进快退暂停调速等视频控制功能有多重要。
15 |
16 | ## 我的快捷键
17 |
18 | 我在用的一组桌面快捷键,
19 | 通过覆盖键盘左侧,实现方便的(左手)单手控制。
20 |
21 | (注意到 [FrontendMasters](https://frontendmasters.com/) 的 Q 键是切换视频质量,有冲突)
22 |
23 | - 通用
24 | - Q:快退 3 秒
25 | - E:快进 3 秒
26 | - Z:播放速度 -0.25
27 | - X:播放速度 +0.25
28 | - V:在(当前播放速度,1)之间切换
29 | - 网页 Only(YouTube 自带)
30 | - T:切换网页全屏
31 | - C:切换字幕/弹幕
32 | - 本地 Only
33 | - PageUp:上一文件
34 | - PageDown:下一文件
35 | - Shift+←:快进 30 秒
36 | - Shift+→:快退 30 秒
37 |
38 | ## 工具
39 |
40 | ### Video Speed Controller
41 |
42 | Chrome 插件:[Video Speed Controller](https://chrome.google.com/webstore/detail/video-speed-controller/nffaoalbilbmmfgbnbgppjihopabppdk)
43 |
44 | ### User JavaScript and CSS
45 |
46 | Chrome 插件:[User JavaScript and CSS](https://chrome.google.com/webstore/detail/user-javascript-and-css/nbhcbdghjpllgmfilhnhkllmkecfmpld)
47 |
48 | 自定义脚本注入插件
49 |
50 | 我在 BiliBili 的配置,实现类似 YouTube 的观看体验。
51 |
52 | ```javascript
53 | {
54 | let maskShown = true;
55 | document.addEventListener('keypress', (e) => {
56 | if (e.key === 't') {
57 | $('.bilibili-player-video-web-fullscreen').click();
58 | }
59 | if (e.key === 'c') {
60 | // * use opacity but not disable the feature
61 | maskShown = !maskShown;
62 | $('.bilibili-player-video-danmaku').css(
63 | 'opacity',
64 | maskShown ? 1 : 0,
65 | );
66 | $('.bilibili-player-video-danmaku-switch').css(
67 | 'opacity',
68 | maskShown ? 1 : 0.1,
69 | );
70 | }
71 | });
72 | }
73 | ```
74 |
75 | ### IINA/PotPlayer
76 |
77 | 都支持快捷键改键
78 |
79 | - [IINA](https://iina.io/):macOS 上的播放器
80 | - [PotPlayer](https://potplayer.daum.net/):Windows 上的播放器
81 |
--------------------------------------------------------------------------------
/docs/note/08.misc/scc/count-lines-of-code.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 代码行数统计工具小测
3 | date: 2020-02-08 20:15:50
4 | permalink: /cs/count-lines-of-code
5 | categories:
6 | - 计算机科学
7 | tags:
8 | - 工具
9 | ---
10 |
11 | # 代码行数统计工具小测
12 |
13 | ## 背景
14 |
15 | 代码量统计可以量化地分析项目中的代码的情况。
16 |
17 | 我最早知道和使用的是 cloc,但是我一直不满意它的运行速度,
18 | 可能小型项目没什么感觉,
19 | 而我处理的项目源码有几十万行的代码量(排除 `node_modules`),
20 | 统计一次需要稳定花费 20s……
21 |
22 | 虽然它的筛选功能很强大,但是实在是太慢了…
23 | 后来我偶然间发现了其他同类工具,直接从 20s 来到 1s,
24 | 太香了!
25 |
26 | 那这些工具有(按字典排序):
27 |
28 | - cloc:
29 | - loc:
30 | - scc:
31 | - tokei:
32 |
33 | 它们有各有差异,诸如:
34 |
35 | - 对文件的默认排除(隐藏文件、`gitignore` 等)策略不同
36 | - 对注释和空行的识别有差异
37 | - 默认的排序项等等
38 |
39 | 但它们都支持一些基本的统计需求:
40 |
41 | - 显示每个文件的独立分析
42 | - 是否包含隐藏文件
43 | - 包含/排除指定文件
44 | - 结果按某列排序
45 | - 总和
46 |
47 | 都是实用的工具。
48 |
49 | ## 简单测试对比
50 |
51 | 先来一些我发现的基本的纸面数据:
52 |
53 | | Repo | Star | 更新 | 语言 | 功能\* | 默认排序 | 速度 |
54 | | :--------------: | :----------: | :----------: | :--: | :----: | :------: | :--: |
55 | | [cloc][cloc-u] | ![][cloc-s] | ![][cloc-l] | Perl | 84 | 代码行数 | 慢 |
56 | | [loc][loc-u] | ![][loc-s] | ![][loc-l] | Rust | 6 | 代码行数 | 快 |
57 | | [scc][scc-u] | ![][scc-s] | ![][scc-l] | Go | 29 | 文件数量 | 快 |
58 | | [tokei][tokei-u] | ![][tokei-s] | ![][tokei-l] | Rust | 14 | 语言类型 | 快 |
59 |
60 | [cloc-u]: https://github.com/AlDanial/cloc
61 | [loc-u]: https://github.com/cgag/loc
62 | [scc-u]: https://github.com/boyter/scc
63 | [tokei-u]: https://github.com/XAMPPRocky/tokei
64 |
65 |
66 |
67 | [cloc-l]: https://img.shields.io/github/last-commit/AlDanial/cloc
68 | [loc-l]: https://img.shields.io/github/last-commit/cgag/loc
69 | [scc-l]: https://img.shields.io/github/last-commit/boyter/scc
70 | [tokei-l]: https://img.shields.io/github/last-commit/XAMPPRocky/tokei
71 |
72 |
73 |
74 | [cloc-s]: https://img.shields.io/github/stars/AlDanial/cloc
75 | [loc-s]: https://img.shields.io/github/stars/cgag/loc
76 | [scc-s]: https://img.shields.io/github/stars/boyter/scc
77 | [tokei-s]: https://img.shields.io/github/stars/XAMPPRocky/tokei
78 |
79 | 还有 tokei 自己做的性能对比:
80 |
81 |
82 | > 注:功能的值来自除了 `help` 以外的参数个数,诸如:
83 | >
84 | > ```bash
85 | > cloc --help | grep -v '\-\-help' | grep -E '^.{0,20}\-\-' | wc -l
86 | > ```
87 |
88 | 可以看到 cloc 是 star 最多的,
89 | 功能也是最丰富的,
90 | 包括它的文档说明也是巨细无遗,
91 | (可惜它是真的慢……)
92 |
93 | 行叭,看看实际干活都怎么样。
94 |
95 | 先找一个巨型仓库:Babel、
96 | 然后是规模小一点的:RxJS、
97 | 最后自己新建了一些文件试试。
98 |
99 | ```bash
100 | git clone --depth=1 https://github.com/babel/babel
101 | git clone --depth=1 https://github.com/ReactiveX/rxjs
102 | git clone --depth=1 https://github.com/seognil-study/cloc-playground
103 | ```
104 |
105 | ## 测试结果
106 |
107 | 直接用最大的 babel 来试试各个工具和结果如何:
108 |
109 | > 注:`time` 是 mac 上统计运行时间用的,
110 | > 打印出来 `total` 左边的数字是实际运行秒数,比如:
111 | >
112 | > ```bash
113 | > time sleep 1
114 | > sleep 1 0.00s user 0.00s system 0% cpu 1.007 total
115 | > ```
116 |
117 | `time cloc --skip-uniqueness babel` ↓
118 |
119 | 
120 |
121 | `time loc --sort=lines babel` ↓
122 |
123 | 
124 |
125 | `time scc -s=lines babel` ↓
126 |
127 | 
128 |
129 | `time tokei -s=lines babel` ↓
130 |
131 | 
132 |
133 | ## 小结
134 |
135 | cloc 确实是最慢的,要花 10s 以上,
136 | (cloc 是否关闭去重功能,其实对速度的影响有限…)
137 |
138 | 而其他工具基本都在 1s 左右,
139 | 这是对于 Babel 仓库 88MB、一万多个文件的情况,
140 | 更小的项目只会更快。
141 |
142 | 另外可以注意到对文件识别上的差别:
143 |
144 | - cloc 没有统计 Plain Text
145 | - loc 将 `ts`/`tsx` 区分成了 `TypeScript`/`Typescript JSX`
146 | - 各个工具找到的文件和统计也有差别
147 |
148 | 我手动 find 的文件数量:
149 |
150 | `find babel -name "*.json" | wc -l`
151 | 结果是 6428,和 `cloc`、`scc` 一致
152 |
153 | `find babel -name "*.js" | wc -l`
154 | 结果是 9436,和 `loc -uu` 一致
155 |
156 | 而诸如代码和注释,每个工具也有所差别,
157 | 比如我发现 JSON 中的注释它们都是不支持的,
158 |
159 | ```json
160 | {
161 | // 注释
162 | /**
163 | * 注释
164 | */
165 | }
166 | ```
167 |
168 | 你说 JSON 不支持注释,为什么 JSON 里有注释?
169 | 实际上在 VS Code 里支持一种语言类型叫 `JSON with Comments`,
170 | 以下文件都支持 JSON + 注释而不会造成失效:
171 |
172 | - VS Code 的 `settings.json`
173 | - Prettier 的 `.prettierrc`
174 | - TypeScript 的 `tsconfig.json`
175 |
176 | 所以统计差异可以理解,
177 | 毕竟这些工具的代码也是人来维护的,
178 | 不可能穷尽和覆盖世界上的所有语言。
179 |
180 | `.jsx` 来自于 React,万一哪天出了 `.jsy`、`.jsz` 新 DSL 呢?
181 | 还有 `.prettierrc` 是什么?(它们都识别不了)
182 |
183 | 实际上 `.prettierrc` 支持 JSON 或 YAML 的不同格式,
184 | 然而如果还要解析语法,这就超出了简单的统计工具的能力范围了。
185 |
186 | 后续我可能会使用 scc,毕竟看上去统计的是最全的,数字是最多的(误
187 | 而且开发复杂度和开发成本估计的功能挺有意思…
188 |
--------------------------------------------------------------------------------
/docs/note/08.misc/scc/img/time-cloc-babel-fs8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seognil/fe-foundation/74290e0ec2a3f0d8cea2c719c6e1dd21a3c2fbb0/docs/note/08.misc/scc/img/time-cloc-babel-fs8.png
--------------------------------------------------------------------------------
/docs/note/08.misc/scc/img/time-loc-babel-fs8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seognil/fe-foundation/74290e0ec2a3f0d8cea2c719c6e1dd21a3c2fbb0/docs/note/08.misc/scc/img/time-loc-babel-fs8.png
--------------------------------------------------------------------------------
/docs/note/08.misc/scc/img/time-scc-babel-fs8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seognil/fe-foundation/74290e0ec2a3f0d8cea2c719c6e1dd21a3c2fbb0/docs/note/08.misc/scc/img/time-scc-babel-fs8.png
--------------------------------------------------------------------------------
/docs/note/08.misc/scc/img/time-tokei-babel-fs8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seognil/fe-foundation/74290e0ec2a3f0d8cea2c719c6e1dd21a3c2fbb0/docs/note/08.misc/scc/img/time-tokei-babel-fs8.png
--------------------------------------------------------------------------------
/docs/note/08.misc/study/dont-waste-your-time-and-money.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 杂谈:你可学点好吧
3 | date: 2021-10-03 16:47:25
4 | permalink: /study/dont-waste-your-time-and-money
5 | categories:
6 | - 学习技巧
7 | tags:
8 | - 杂谈
9 | ---
10 |
11 | # 杂谈:你可学点好吧
12 |
13 | 我叫 LC,现在在做前端开发。
14 |
15 | 我刚入行的时候,当时缺少大佬的指点,自己的认知水平也不太行。走了很多弯路,看过很多粗制滥造或的教程。
16 |
17 | 所谓走弯路。用最近新学到的一个词 **ROI**(Return On Investment),即**投入产出比**来解释。对于学习而言,投入具有多种形态:时间、精力、金钱、情绪等,而最直观的产出则是是否学会了某项技能。所谓走弯路即是 ROI 低,效率低。
18 |
19 | 现在随着我的技能水平和视野不断提升,我已经接触到了很多优秀的资料,也认识了一些能给我指引方向的人,甚至我自己也逐渐成为别人眼中专业的人。今天的我如果穿越回去重新教自己,肯定少走一些弯路。
20 |
21 | 比方说时间角度,知道了从哪获取优质的、专业的、由浅入深的、合适的资料,避免大海捞针式地看低质的、业余的资料。有效信息密度提高了,学习效率自然也就高了。
22 |
23 | 经济角度,问题转而变成:我如何便宜地筛选和获取这些优秀资料?
24 |
25 | 其中有一个我觉得最亏的一笔支出,那是我花了一万多块买了一套为期几个月的“高级前端进阶课程”(具体名字忘了,反正都这个味儿)。
26 |
27 | ## 故事
28 |
29 | 当时比较 naive。试听了几个小时,看了下他们的课程大纲,对标大厂 P 几 T 几,挑战年薪几十万。我以为贵自然有贵的道理,一套十全大补汤下来我的水平肯定能再提高一个段位。
30 |
31 | 也确实不错,想必对于很多初级前端来说或许真的能让他们快速入行,或者跳槽的时候工资翻倍。
32 |
33 | 我自己也是有所收获。JS 的语言标准 ECMA-262、JS runtime 的 Execution Context Stack、Node.js 垃圾回收原理等概念我最早就是从这儿知道的。
34 |
35 | **但也仅限于此了**。
36 |
37 | 当时我已经看过一些文章和书,有一些工程经验和理论储备了。所以课程中讲的很多理论性内容我早就知道了,高程和小黄书上都有嘛,无非就是用刁钻题再多训练几遍。但这没什么意义,实际工程中最佳实践是提倡少写骚代码的。
38 |
39 | 举个例子。我现在写项目,`function`、`class`、`this`、`var`、`==` 这些基本不用。现在 React 推行函数式编程,我直接箭头函数、`const`、外加 ESLint 和 TypeScript 拉满就好了。精通 this 的四种写法干嘛呢?手写 ES5 继承和 new?这些知道下概念以后能看懂不就好了?精通八股文是哪门子的高级?
40 |
41 | 框架类库的实战训练课程也就是教下概念,调调 API 糊个玩具项目,还有面试装逼用的源码解析环节。但是没接触过的工具我不能自己学啊?官方文档、Demo、视频教程、源码解析这些网上遍地都是啊?碰到瓶颈了多用用 Stack Overflow、看看不同的解释不就完事了?
42 |
43 | 啊,还有什么前端图形学。听上去高大上,搞半天用下 three.js 而已,还以为会科普下 pbr 之类的呢…
44 |
45 | 就这?
46 |
47 | 所以总体来说并没有达到我对一个五位数级别知识付费的期望。除了最开始可能十个小时的内容我全部听完了,也刷了一些题目,之后基本就没再怎么打开过。
48 |
49 | ## 技术培训产业
50 |
51 | 有的小可爱比较机灵:那我去咸鱼买盗版,去网盘直接下各种全集,我也不是大佬,好歹能查漏补缺,学到点东西,白嫖总不会亏吧?
52 |
53 | 真不亏吗?之前提到,投入是具有多种形态的。培训机构只不过是没赚到一些钱而已,可你却失去了宝贵的时间啊!
54 |
55 | 我前几年零散看(嫖)过一些国内的视频教程(包括刚才提到的,以及像网易云课堂、慕课网、黑马之类的)。无论收费免费,大部分质量都很一般,甚至还有:
56 |
57 | 个别讲师对技术的理解僵化,教条主义,照本宣科。
58 | 个别讲师搞起直播文化,求弹幕刷礼物,不知道的还以为娱乐主播呢。
59 |
60 | 稍有经验的前端工程师应该都清楚前端**技术更新**的速度。如果不是长期参与实际项目、拥有扎实的基础训练、并不断思考,光靠别人把知识灌到自己的脑子里是很难理解到**技术的本质**、形成对技术的判断力和直觉的。
61 |
62 | 以状态管理为例,培训班顶多教教 Redux、Vuex 啥的速成一下,撑死了讲源码甚至手写一个。但我在工作中实际接触过的状管工具不下十个,做针对性项目选型、需求分析、看论文、自研。哪个培训班能提供这些冰山以下的东西?时间有限,大部分声称高大上的课程,都只是入个门而已。
63 |
64 | 此外我有时会直接关注业界的最新动向,看看大佬们在干什么:
65 |
66 | - **Dan Abramov**:Redux 的作者,React 核心开发者
67 | - **Dmitry Soshnikov**:JavaScript: The Core 的作者
68 | - **Douglas Crockford**:JavaScript: The Good Parts 的作者
69 | - **Evan You**:Vue.js 的作者
70 | - **Robert C. Martin**:Clean Code 的作者
71 |
72 | 又有哪个培训班有这种教学资源?
73 |
74 | ## 如何学习
75 |
76 | 说到底是市场人才需求的膨胀以及人们的职业焦虑,影响培训产业也快速发展。
77 |
78 | 培训班的商业模式就是靠卖课恰饭嘛,恰饭多香啊。但很多有能力的人直接在开发者大会上做分享,搞开源项目拿赞助,给大厂做付费咨询。他们走另外的赛道了,会稀得开这种恰饭的培训班吗?
79 |
80 | 哦也是有的,我也确实认识一些创业做培训或是副业技术自媒体的大佬。恰饭嘛,不寒碜。广义上来讲,大学不也是付费培训班呗……我看过 CMU、Stanford 的公开课和教材,也听过尤雨溪讲 Vue、Dan 讲 Redux 的完整课程。
81 |
82 | 所以倒不是培训班本身不好,而是产业规模化之后整体质量的下滑或内卷跑偏,导致获取优质信息的成本变大了。
83 |
84 | 暂停一下,所以…不是培训班本身不好…吗?我认为本质问题也不在这,获取资源的成本先不谈,我认为培训班或者说系统性课程在形式上也有局限性。
85 |
86 | 学前端的时候来一套课程,那之后学后端和其他技术栈呢?想做投资,了解下商业、经济、法律呢?教育、心理学、沟通能力这些呢?生活技能像吉他、摄影、写作、烹饪、健身这些呢?全靠所谓的培训吗?就算钱包受得住(家里有矿是吧),时间也顶不住啊。
87 |
88 | 通常我们的需求只是够用就好,不可能对每个领域都进行无限的投入并以成为该领域专家为目标。
89 |
90 | 所以,我现在看待培训班,并不把它当做标准答案甚至救命稻草,反而是一个参考、一种学习工具。它就像电脑、技术框架、书一样都是工具。好的工具拿来用,不趁手的工具就不用。我们需要的不是“鱼”的结果而是“渔”的技巧。做工具的主人,不断形成自己的思考,训练和掌握主动检索信息的能力,才能多快好省地学到东西,更高效地实现自我提升。
91 |
92 | 现在那种成套的培训班视频我基本不看了(新领域也如此)。把钱用来买订阅服务和书(书可太便宜了),把时间用来看 Youtube 上的各种 Crash Course、开发者大会、官方文档、经典书籍、论文、技术专栏、博客……
93 |
94 | > You don’t need college to learn stuff
95 | > Everything is available basically for free
96 | > You can learn anything you want for free
97 | >
98 | > -- [Elon Musk knocks the college experience](https://www.youtube.com/watch?v=Io3sdAAcZLw)
99 |
100 | ## 参考资料
101 |
102 | - [前端职业规划 - 2021 年](https://github.com/ascoders/weekly/blob/master/%E5%89%8D%E6%B2%BF%E6%8A%80%E6%9C%AF/196.%E7%B2%BE%E8%AF%BB%E3%80%8A%E5%89%8D%E7%AB%AF%E8%81%8C%E4%B8%9A%E8%A7%84%E5%88%92%20-%202021%20%E5%B9%B4%E3%80%8B.md)
103 | - [中国的程序员数量是否已经饱和或者过剩?](https://www.zhihu.com/question/356982241/answer/1010277323)
104 | - [【李自然说】在线教育,又一个伪风口?](https://www.bilibili.com/video/BV114411r74i/)
105 | - [你能做我的 mentor 吗 - 湾区日报](https://wanqu.co/a/7452/%E4%BD%A0%E8%83%BD%E5%81%9A%E6%88%91%E7%9A%84-mentor-%E5%90%97/)
106 |
--------------------------------------------------------------------------------
/docs/note/08.misc/study/study-fortune.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 关于学习的鸡汤
3 | date: 2019-12-29 16:08:12
4 | permalink: /study/study-fortune
5 | categories:
6 | - 学习技巧
7 | tags:
8 | - 杂谈
9 | ---
10 |
11 | # 关于学习的鸡汤
12 |
13 | ## TLDR
14 |
15 | 我觉得最重要的三点([学习方法论](/study/crash-course-study-skills)):
16 |
17 | - 学得会并记得住
18 | - 大量搜集资源
19 | - 掌握解决问题的思维(DEBUG)
20 |
21 | ## 持续前进
22 |
23 | - [【C 菌】全是干货!GPA4.0 研究生 UP 主教你学习诀窍!](https://www.bilibili.com/video/av63716273/)
24 | - [永远投资你的教育](https://wanqu.co/a/4092/%E6%B0%B8%E8%BF%9C%E6%8A%95%E8%B5%84%E4%BD%A0%E7%9A%84%E6%95%99%E8%82%B2/)
25 | - [A Valuable Lesson For A Happier Life](https://www.youtube.com/watch?v=SqGRnlXplx0)
26 |
27 | > 学而时习之 温故而知新 —— 孔子
28 |
29 | 保持兴趣,循序渐进
30 | 广泛涉猎,融汇贯通
31 |
32 | 编程是理科,同时也是工科。
33 | 行业中有一些部分,可能并不是极难的研发性质的工作,
34 | 仅仅只是学习前人的经验,并仿照着实现而已。
35 |
36 | 根据自己当前的水平适当调整节奏。
37 | 不要经历“习得性无助” —— “我总是不行,太难了,做不了。”
38 | 反之,不断给自己创造微小的成就感,持之以恒就能点亮整片技能树。
39 |
40 | ~~(曾经我周末花了一整天,仅仅在反复琢磨 node 和 npm 的版本和安装卸载,并在之后快乐了一个星期)~~
41 |
42 | ## 练习英语
43 |
44 | [英语 训练指南(编程篇)](/study/using-english)
45 |
46 | ## 工程师思维
47 |
48 | 养成解决问题的习惯,而不仅仅是能够解决问题。
49 | 学会发现问题,而不是人云亦云。
50 | (这也是工作和上学最大的区别之一)
51 |
52 | 随着工作经历的增加,一定会碰到无数之前没有见过的问题、知识、技能需要学习。
53 | 这其中有的新技能是通用的,掌握之后是可以长期受用的,
54 | 也有一些问题,仅仅是暂时的,以后永远不会再碰到的。
55 | (当然,能够提前区分这两种类型也需要靠不断的经验积累)
56 |
57 | 那么通过预先学习来覆盖所有情况是不现实的。
58 | 所以要学会即时发现新的问题,并运用一定的技巧去尝试解决,
59 | 比如基于本站的文章,就能产生很多问题:
60 |
61 | - “很多资料链接都是英文的,以我目前的英语水平会很吃力,有没有可能已经有翻译版了呢”
62 | - “这个概念我不懂,文中的解释也不够充分,我从哪里可以查阅呢”
63 | - “我从不同的地方看到了相反的答案,如何判断哪个是正确的呢”
64 | - “这是别人的心得,我如何定制适合自己的计划呢”
65 | - “这个工具我用着很别扭,有什么方式可以改进呢”
66 |
67 | 互联网上有无数免费和付费的资料。
68 |
69 | ## 理解编程
70 |
71 | [计算机科学 入门指南](/cs/crash-course-computer-science)
72 |
73 | 了解框架原理,而不是背诵框架 API。
74 | 学习编程思想,而不是深究实现细节。
75 | (比如不要在初学阶段沉迷研究 JS 里的隐式类型转换具体规则)
76 |
77 | 你是工具的主人,不是工具的奴隶,
78 | 语言、框架、软件、电脑是你的工具。
79 | 了解工具的性质,更好地使用它们。
80 |
81 | ### 调整心态
82 |
83 | 前期避免过度追求变现,
84 | 优先追求掌握技能和创造价值,
85 | 有技术水平才能有议价能力。
86 |
87 | (说人话:不要太关心能拿多高的工资)
88 | (但是也要考虑工作和学习、生活的平衡)
89 |
90 | 面向解决技术问题开发,而不是面向解决具体业务开发。
91 | (如果有机会的话…)
92 |
93 | ~~尤其是在互联网资本寒冬的现在(真的吗?)~~
94 | 夯实基础,稳步前进。
95 |
96 | ### 费曼学习法
97 |
98 | [【思维论 03】费曼学习法的误区:为什么学渣给学霸讲题,学习收益才更高?](https://www.bilibili.com/video/av88910392)
99 |
100 | 我理解的一句话版本:
101 |
102 | > 如果你能将一个概念完整地教会别人,那么说明你掌握了它。
103 |
104 | 对于任何一个知识/技术体系来说,
105 | 你第一次发现它的时候,它还不属于你,
106 | 你只能通过查阅来弄懂。
107 |
108 | 而当你不断地在脑海中构建和修正出自己的结构化体系,
109 | 你能够基于自己的体系,在脑海中直接快速地检索到它的每一个细节,
110 | 那么你就掌握了它。
111 |
112 | ### 小黄鸭调试法
113 |
114 | > 小黄鸭调试法,又称橡皮鸭调试法、黄鸭除虫法(Rubber Duck Debugging)是可在软件工程中使用的一种调试代码的方法。方法就是在程序的调试、调试或测试过程中,操作人耐心地向小黄鸭解释每一行程序的作用,以此来激发灵感与发现矛盾。
115 |
116 | 看似很胡扯,但是其实是非常严肃的道理。
117 |
118 | > 就在解释的过程中,程序员可能就发觉了问题的解决方案。
119 |
120 | 程序的运作,代码的运行都是有据可循的:
121 | 运行结果不符合预期,肯定是某一步或者某几步出了问题。
122 | 通过不断拆分步骤并逐步分析,就能定位到问题所在,才能试图解决它。
123 |
124 | ### 编程训练
125 |
126 | > 限制方法的灵活性几乎总能使你把事情做得更好。 —— DOOM 之父 约翰卡马克
127 | > 学而不思则罔,思而不学则殆 —— 孔子
128 | > 最高级的想象力是不自由的 —— 同人于野
129 |
130 | 一定要向古老的智慧学习,理解久经考验的技术思路的精髓。
131 |
132 | 算法、设计模式、范式、特性、规范、协议等等,各式各样的名词…
133 | 不严谨地来讲,我认为指的都是同一件事 —— 别人总结的成熟可靠的经验。
134 |
135 | > 纸上得来终觉浅,绝知此事要躬行 —— 陆游
136 |
137 | 同时,写代码这件事,只能通过反复的实际编写运行和推敲才能掌握,
138 | 才更有机会形成(潜意识的)技术直觉。
139 | (就像学会开车)
140 | ~~(就像上文中我反复安装 node 的故事那样)~~
141 |
142 | > Learn fast, Learn Cheap
143 | > 工欲善其事,必先利其器 —— 孔子
144 |
145 | 软件工程中有敏捷开发的概念,学习本身也可以敏捷化。
146 | 想办法优先提高效率。(即使这个过程很耗时)
147 |
148 | 举个例子:在仿写 JS 代码的时候如何快速运行?
149 | 打开浏览器的 devtools 手动敲吗?
150 | 更好的方式是:利用 [VS Code](/workspace/vscode) + [Code Runner](https://marketplace.visualstudio.com/items?itemName=formulahendry.code-runner) + [Quokka.js](https://marketplace.visualstudio.com/items?itemName=WallabyJs.quokka-vscode)
151 |
152 | ### Environment/Body/Mind
153 |
154 | [每月高效工作 200 小时](https://wanqu.co/a/5765/%E6%AF%8F%E6%9C%88%E9%AB%98%E6%95%88%E5%B7%A5%E4%BD%9C-200-%E5%B0%8F%E6%97%B6/)
155 |
156 | 利用环境和工具
157 | 保持健康的身体和清醒的头脑
158 | 自我激励和自我意志
159 |
160 | 适当休息暂停学习,长期来看反而能产生更大的效益(边际效益最大化)
161 |
--------------------------------------------------------------------------------
/docs/note/08.misc/study/why-we-need-to-study.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 杂谈:我们为什么需要读书和学习
3 | date: 2021-10-02 13:13:35
4 | permalink: /study/why-we-need-to-study
5 | categories:
6 | - 学习技巧
7 | tags:
8 | - 杂谈
9 | ---
10 |
11 | # 杂谈:我们为什么需要读书学习
12 |
13 | > 要说这世界有多少本书
14 | > 仿佛这世间来过多少个人就有多少本书
15 | > 有的书只写到了目录
16 | > 有的书全是过往的痕迹
17 | > 虽然时光会让新书变旧
18 | > 但文字却不会因岁月沧桑
19 | > 空出两格另起一段
20 | > 辗转反侧再写一行
21 | > 要到何处埋下伏笔
22 | > 又在何处会惊艳全场
23 | >
24 | > -- [《图 书 馆 子》- 巫托邦](https://www.bilibili.com/video/BV1J64y187C3)
25 |
26 | ## 浅谈
27 |
28 | 人类还不具备(像黑客帝国一样)直接下载知识技能到大脑的能力。
29 |
30 | 从最初的牙牙学语和直立行走,到基础义务教育,再到通过专业技能进行劳动创造社会价值。
31 | 一切知识技能都需要通过缓慢而长期地学习和训练获得。
32 |
33 | 抽象地来说:学习的过程,其实是人体这个碳基系统**训练新的输入输出响应**的过程,
34 | 这个过程将会更新肌肉以及人体各部分的生物设施,以及不断塑造新的大脑**神经通路**。
35 |
36 | 正如古人所云:
37 |
38 | > 纸上得来终觉浅,绝知此事要躬行。
39 |
40 | 我们不断地向他人学习、通过历史资料学习,学习那些前人已经帮我们总结出的经验,从而与当今的世界共存,同时不断创造出新的知识。
41 |
42 | ## 扩展阅读
43 |
44 | - [B 站 UP 主:智能路障](https://space.bilibili.com/79577853)
45 | - [2020 世界读书日 节目](https://www.bilibili.com/video/BV1T5411w7yh)
46 | - [读书又不能赚钱,那么读书到底有什么用呢?](https://www.bilibili.com/video/BV1ug4y187W7)
47 | - [2021 世界读书日 节目](https://www.bilibili.com/video/BV1T5411w7yh)
48 | - [读书和成功有必然联系吗?我们为什么要读书?](https://www.bilibili.com/video/BV1RQ4y1177C)
49 | - 湾区日报
50 | - [最好的投资](https://wanqu.co/a/4701/)
51 | - [巴菲特公式](https://wanqu.co/a/4065/2016-10-12-the-buffett-formula/)
52 | - [五个比 Bitcoin 更好的投资](https://wanqu.co/a/6067/%E4%BA%94%E4%B8%AA%E6%AF%94-bitcoin-%E6%9B%B4%E5%A5%BD%E7%9A%84%E6%8A%95%E8%B5%84/)
53 | - 短片小说
54 | - [他们是肉造的 - 泰利·比森](https://www.zhihu.com/question/321878154)
55 | - [乡村教师 - 刘慈欣](http://www.00txt.com/xiangcunjiaoshi/2033.html)
56 |
--------------------------------------------------------------------------------
/docs/note/10.frontend/02.javascript/1.javascript-foundation.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: JavaScript 学习指南 *
3 | date: 2019-08-08 18:36:05
4 | permalink: /frontend/javascript-foundation
5 | categories:
6 | - 前端开发
7 | - JavaScript
8 | tags:
9 | - JavaScript
10 | ---
11 |
12 | # JavaScript 学习指南 \*
13 |
14 | \* 撰写中
15 |
16 | ---
17 |
18 | > 查看旧版 [JS Foundation(旧)](/frontend/javascript-foundation-legacy-version)
19 |
20 | ---
21 |
22 | 我自己目前在 JavaScript 本身上的学习可能已经累计超过 200~500 小时。
23 | (甚至还没进入核心层面,只能算略懂,甚至有一些理解偏差)
24 |
25 | ## 大致路线图
26 |
27 | 对于**学习 JavaScript 语言**来说,我认为合适的方式大致是:
28 |
29 | - 准备:预先理解最基本的编程思想
30 | - 入门:熟悉 JavaScript 基本语法,了解 JavaScript 的大致样貌
31 | - 熟悉:练习 JavaScript 常用内置对象的常用 API 用法
32 | - 实战:熟悉 JavaScript 能够进行的进行实际开发
33 | - 深入:了解 JavaScript 深层次的语言特性和原理
34 |
35 | ## JavaScript 知识体系结构图
36 |
37 | - **前置学习**
38 | - [前端开发入门指南](/note/frontend-development-cookbook)
39 | - **JavaScript**
40 | - [JavaScript 简介](/frontend/introduction-to-javascript)
41 | - [运行 JavaScript 代码的十几种方式](/frontend/how-to-run-javascript-code)
42 | - **JavaScript 语言核心**
43 | - [JavaScript 语言基础(2021)](/cs/javascript-language-basic)
44 | - [JavaScript 进阶指南](/frontend/javascript-advanced)
45 | - JavaScript 硬核指南(TODO)
46 | - [前端模块化](/frontend/javascript-modules)
47 | - _JavaScript 内置对象_
48 | - [正则表达式](/frontend/javascript-regular-expression)
49 | - Promise(TODO)
50 | - [语法糖、操作符、关键字、特性](/frontend/syntactic-sugar-in-javascript)
51 | - **JavaScript 编程**
52 | - JavaScript DOM 编程指南(TODO)
53 | - 事件、代理事件
54 | - 本地存储
55 | - JavaScript 异步编程(TODO)
56 | - JavaScript 网络开发指南(TODO)
57 | - ajax、fetch、跨域、cookie
58 | - JavaScript 移动端开发指南(TODO)
59 | - TouchEvent
60 | - 传感器(陀螺仪等)
61 | - **Node.js 和 NPM**
62 | - [Node.js 入门指南](/frontend/nodejs-basic)
63 | - [npm 基本概念和使用](/frontend/introduction-to-npm)
64 | - [用 Proxy 进一步提高 npm 安装速度](/frontend/speeding-up-npm-install)
65 | - [使用 verdaccio 搭建私有 npm 仓库](/frontend/set-up-a-private-npm-registry-using-verdaccio)
66 | - Node.js 踩坑记录
67 | - 开发和发布一个 npm 包(TODO)
68 |
--------------------------------------------------------------------------------
/docs/note/10.frontend/02.javascript/2.introduction-to-javascript.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: JavaScript 简介
3 | date: 2019-12-30 11:39:54
4 | permalink: /frontend/introduction-to-javascript
5 | categories:
6 | - 前端开发
7 | - JavaScript
8 | tags:
9 | - JavaScript
10 | ---
11 |
12 | # JavaScript 简介
13 |
14 | ## 什么是 JavaScript
15 |
16 | JavaScript(通常缩写为 JS)是一种解释型高级语言。
17 | 通常作为开发 Web 页面的脚本语言,
18 | 但是它也可以在非浏览器环境中使用,例如 Node.js。
19 |
20 | 广义的 JavaScript 包含三个部分:
21 |
22 | - `ES`:ECMAScript,核心标准
23 | - `DOM`:Document Object Model,文档对象模型
24 | - `BOM`: Browser Object Model,浏览器对象模型
25 |
26 | 狭义的 JavaScript 可以只指 `ECMAScript`,
27 | 可以简单理解为浏览器、Node 嵌入式等所有环境都必须支持的 JS 功能子集。
28 | (去掉了 `document`、`window` 等概念)
29 |
30 | [JavaScript 是图灵完备的](https://www.freecodecamp.org/news/javascript-is-turing-complete-explained-41a34287d263/)
31 |
32 | ## 什么是 ES6
33 |
34 | ES 就是 ECMAScript,
35 | ES2015/ES6 是 ES 的一个里程碑(大更新)版本,
36 | 其中 2015 表示年份,6 表示版本号,
37 | (目前最新的是 ES2019/ES10)
38 | ES6+ 是前端开发的基本语言。
39 |
40 | - ES6 相比 ES5:
41 | - 多了一些语法
42 | - 或需要被预编译成 ES5 以增加旧环境兼容性
43 | - 多了一些 API
44 | - 或需要 Polyfill
45 | - 多了一些数据结构和类型
46 | - 或可以被预转译
47 | - 部分特性无法被完美模拟(如 Proxy)
48 |
49 | * 兼容性
50 | - [ECMAScript 6 compatibility table - kangax](https://kangax.github.io/compat-table/)
51 | - [Can I use Arrow functions ?](https://caniuse.com/#search=Arrow%20functions)
52 |
53 | ## 为什么要学习 JavaScript
54 |
55 | - 如果你想编程入门
56 | - 如果你想魔改某些页面
57 | - 如果你想从事前端开发工作
58 |
59 | ## JS 概况/漫谈
60 |
61 | - [硬核前端(劝退篇)](/frontend/frontend-hardcore-overview)
62 |
63 | - [王垠对 JS 的评价](https://zhuanlan.zhihu.com/p/54821270)
64 |
65 | * [2019 年 JavaScript 明星项目](https://risingstars.js.org/2019/zh)
66 | * [2018 年 JavaScript 明星项目](https://risingstars.js.org/2018/zh)
67 | * [The State of JavaScript 2019](https://2019.stateofjs.com/zh/)
68 |
69 | - [为什么认为 Backbone 是现代前端框架的基石](https://zhuanlan.zhihu.com/p/30982369)
70 | - [[译文] 现代 js 框架存在的根本原因](https://juejin.im/post/5b111436e51d4506d06205fd)
71 |
72 | ## JavaScript 版本/方言/历史
73 |
74 | - [JavaScript: The First 20 Years](https://zenodo.org/record/3710954)
75 | - [The Weird History of JavaScript](https://www.youtube.com/watch?v=Sh6lK57Cuk4)
76 | - [JavaScript: How It's Made](https://www.youtube.com/watch?v=FSs_JYwnAdI)
77 | - [漫谈 JavaScript 方言与派系](https://www.blackglory.me/javascript-dialects-and-factions/)
78 |
79 | 在现代前端开发中,
80 | 开发时需要使用配套的解析工具,
81 | 发布前基本上都会预编译到 ES5。
82 |
83 | - **ECMAScript** 官方规范(from _Ecma TC39_)
84 | - **ES1~3**:1995 起,上古版本
85 | - **ES5**:(aka `ES3.1`)2009 起的版本
86 | - **ES6**:(aka `ES2015`)2015 年大更新的版本,带动了 JS 预编译生态,后续逐年小幅度更新
87 | - **Vanilla JavaScript**:民间称呼,指的就是标准/原生/不使用库的 JS,Vanilla 表示 Plain 或者 Pure
88 | - **JSON**: JavaScript Object Notation,JS 对象表示法,基于 JS 语法子集的数据格式
89 | - 类型系统
90 | - **TypeScript**:带类型检查的扩展集(from _Microsoft_)
91 | - **Flow**:比 TS 功能少一点的类型检查扩展集,现已式微(from _Facebook_)
92 | - 框架语言(基于 ES、TS 并含有扩展语法的 DSL/语法糖)
93 | - **JSX**:React 的 JS + HTML 混合语法
94 | - **Vue**:Vue 自己的(文件和 template)格式
95 | - **ClojureScript**:Clojure+JS 的函数式方言
96 | - 其他方言(现已式微的)
97 | - **ActionScript**:以 ES4 衍生发展成的旁支(用于 _Adobe_ Flash,但是 Flash 已死)
98 | - **CoffeeScript**:方言之一,简化了 JS 语法
99 | - **LiveScript**:CoffeeScript 的兄弟版本(JS 早期曾用名也是这个,但是不同的东西)
100 |
--------------------------------------------------------------------------------
/docs/note/10.frontend/02.javascript/4.javascript-advanced.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: JavaScript 进阶指南 *
3 | date: 2019-12-30 11:39:54
4 | permalink: /frontend/javascript-advanced
5 | categories:
6 | - 前端开发
7 | - JavaScript
8 | tags:
9 | - JavaScript
10 | ---
11 |
12 | # JavaScript 进阶指南 \*
13 |
14 | \* 撰写中
15 |
16 | ## 学习 JavaScript 进阶知识
17 |
18 | ### 概览
19 |
20 | - 耗时:
21 | - 深入 JS 语言特性和编程技巧,耗时大约 60~120 小时
22 | - 难点:略
23 | - 工具:略
24 |
25 | ### 学习路线
26 |
27 | - 前置学习
28 | - [JavaScript 语言基础(2021)](/cs/javascript-language-basic)
29 | - 学习 JavaScript 高级特性
30 | - 看书、看视频 ↓,掌握下文中的提到的 JS 进阶知识体系
31 | - 实战
32 | - 刷题 ↓
33 | - 迷思
34 | - 什么是元编程
35 | - 什么是反射
36 | - 什么是运算符重载,JS 里能不能实现
37 |
38 | ## 资料
39 |
40 | ### 自学教材
41 |
42 | - 书籍
43 | - [你不知道的 JavaScript](https://book.douban.com/series/40642):小黄书,中卷 全部
44 | - [JavaScript 忍者秘籍](https://book.douban.com/subject/26638316/):忍者书,全部
45 | - [JavaScript 语言精粹](https://book.douban.com/subject/3590768/):蝴蝶书,全部
46 | - 视频
47 | - [The JavaScript Survival Guide](https://www.youtube.com/watch?v=9emXNzqCKyg)
48 | 14 分钟:JS 基本技巧和特性细节
49 | - [JavaScript Pro Tips - Code This, NOT That](https://www.youtube.com/watch?v=Mus_vwhTCq0)
50 | 12 分钟:JS 编码修养
51 | - [The Future of JavaScript - New Features and Disruptive Trends in 2020](https://www.youtube.com/watch?v=f0DrPLKf6Ro)
52 | 10 分钟:ES2020 新特性介绍
53 | - [JavaScript: Understanding the Weird Parts - The First 3.5 Hours](https://www.youtube.com/watch?v=Bv_5Zv5c-Ts)
54 | - 扩展阅读
55 | - [i=1 为什么(++i)+(++i)=6?](https://www.zhihu.com/question/347864795)
56 |
57 | ### 刷题教材
58 |
59 | 同样的道理,可能会有很多重复的题,选择性跳过,建立自己的知识体系
60 | 注意到纯 JS 和 DOM 编程的题可能会混在一起,可以考虑分开刷
61 |
62 | - 代码片段
63 | - [JavaScript - 30 seconds of code](https://www.30secondsofcode.org/js/p/1)
64 | - 在线刷题
65 | - [codewars](https://www.codewars.com/?language=javascript)
66 | - 别人整理的题目(按字典排序)
67 | - [JavaScript - FE-Interview-Questions](https://github.com/poetries/FE-Interview-Questions/blob/master/JavaScript.md)
68 | - [JavaScript - 前端硬核面试专题](https://github.com/biaochenxuying/blog/blob/master/interview/fe-interview.md#4-javascript):第四章(JS)、第五章(ES6+)
69 | - [JavaScript 开发者应懂的 33 个概念](https://github.com/stephentian/33-js-concepts):(可以先排除设计模式、算法的部分)
70 | - [JavaScript 进阶问题列表](https://github.com/lydiahallie/javascript-questions/blob/master/zh-CN/README-zh_CN.md)
71 | - [javaScript 问题 - FEGuide 前端指南](https://github.com/FEGuideTeam/FEGuide/tree/master/javascript%E9%97%AE%E9%A2%98)
72 | - [JS - 前端进阶之道](https://github.com/InterviewMap/CS-Interview-Knowledge-Map/blob/master/JS/JS-ch.md)
73 | - [JS 相关问题 - 前端工作面试问题](https://github.com/h5bp/Front-end-Developer-Interview-Questions/blob/master/src/translations/chinese/README.md#js-%E7%9B%B8%E5%85%B3%E9%97%AE%E9%A2%98)
74 | - [JS 进阶 - 前端每日一问](https://github.com/sanyuan0704/frontend_daily_question#js-%E8%BF%9B%E9%98%B6):JS 的部分
75 | - [搞搞 js - PersonalBlog Nealyang 全栈前端](https://github.com/Nealyang/PersonalBlog#%E6%90%9E%E6%90%9Ejs):JS 部分(语言本身相关的那些)
76 | - [深入系列目录 - 冴羽的博客](https://github.com/mqyqingfeng/Blog#%E6%B7%B1%E5%85%A5%E7%B3%BB%E5%88%97%E7%9B%AE%E5%BD%95)
77 |
78 | ## JavaScript 进阶知识体系
79 |
80 | ### JavaScript 进阶概念
81 |
82 | - 语言特性
83 | - 变量
84 | - 基本类型 vs 引用类型、按值传递
85 | - 类型转换、隐式类型转换(`toString`/`valueOf`)
86 | - 变量提升
87 | - 函数
88 | - `length`、`name`、`prototype`
89 | - `this`、`arguments`
90 | - 立即执行函数表达式(IIFE)、高阶函数
91 | - 闭包、作用域、`eval`、内存泄露
92 | - ES6:箭头函数、剩余参数、默认参数
93 | - 数组
94 | - Array-Like(如 `arguments` 等)
95 | - 对象
96 | - `prototype`、`constructor`
97 | - 原型链
98 | - ES6 对象
99 | - `Promise`、`Generator`、`async`
100 | - `Map`、`Set`
101 | - `Proxy`
102 | - Array-Like(如 `BigUint64Array` 等)
103 | - 正则表达式
104 | - 前端模块化
105 | - 执行原理
106 | - 短路计算
107 | - IEEE754 问题
108 | - EventLoop
109 | - 垃圾回收
110 | - 前瞻(2020)
111 | - ES 新特性(含草案)
112 | - 动态引入:`await import('lib')`
113 | - 可选链:`user?.shooping?.list`
114 | - Nullish Coalescing:`const animeTime = duration ?? 400`
115 | - BigInt
116 | - Node
117 | - Worker Threads
118 | - ES module support
119 |
120 | ### JavaScript 编码素养
121 |
122 | - 语言精粹/毒瘤
123 | - 多用
124 | - 分号、花括号
125 | - ES6 新特性(解构、模板字符串)
126 | - 静态检查器([ESLint](https://eslint.org/))、自动格式化([Prettier](https://prettier.io/))
127 | - 少用
128 | - 显式全局变量、未定义变量、隐式 Falsy、`==`
129 | - `with`、`eval`、`label`、`switch`、`void`
130 | - `++`、`--`
131 | - 提高编码技巧
132 | - `console` API
133 | - 对象处理、数组处理
134 | - `async`
135 | - 手写系列
136 | - 对象:组合寄生继承
137 | - 数组:`map`/`filter`/`reducer` 的 Polyfill
138 | - 模拟实现 `new`/`bind`/`call`/`apply`/`instanceof`
139 | - `Promise`
140 | - `deepClone`、`deepFlatten`
141 | - 函数:`debounce`/`throttle`
142 | - 集合:`unique`/`union`
143 | - 事件:EventEmitter/EventBus
144 |
--------------------------------------------------------------------------------
/docs/note/10.frontend/02.javascript/7.javascript-regular-expression.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 正则表达式 学习指南
3 | date: 2019-12-26 18:39:31
4 | permalink: /frontend/javascript-regular-expression
5 | categories:
6 | - 前端开发
7 | - JavaScript
8 | tags:
9 | - JavaScript
10 | - 正则表达式
11 | ---
12 |
13 | # 正则表达式 学习指南
14 |
15 | ## 正则表达式 简介
16 |
17 | ### 什么是 正则表达式
18 |
19 | > 正则表达式(英语:Regular Expression,常简写为 regex、regexp 或 RE),又称正则表示式、正则表示法、规则表达式、常规表示法,是计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些符合某个模式的文本。
20 |
21 | 正则不仅在 JavaScript 中存在,
22 | 很多其他主流语言以及工具都支持正则,
23 | 例如:
24 |
25 | - [JS 中的 RegExp 对象](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/RegExp)、[python 中的 `re` 模块](https://docs.python.org/zh-cn/3/library/re.html)
26 | - Unix 中的 `sed` 命令、`grep` 命令的 `-E` 参数
27 | - 几乎所有代码编辑器的搜索功能:VS Code、Sublime Text、vim、IntelliJ IDEA 系列
28 | - [Chrome 正则搜索插件](https://chrome.google.com/webstore/detail/chrome-regex-search/bpelaihoicobbkgmhcbikncnpacdbknn)
29 |
30 | #### 正则表达式 概念分类
31 |
32 | - 转义字符
33 | - 位置匹配(边界,如单词边界、行开头)
34 | - 组合和量词
35 | - 正则中具有多种功能的字符们
36 | - `()`, `?`, `^`, `\`, `$`
37 | - 断言(边界,预测前后字符串)
38 | - flags(不同的检索策略,如是否忽略大小写)
39 |
40 | ### 为什么要用 正则表达式
41 |
42 | 展开说可以有更多具体的使用场景,
43 | (比如完成业务需求或在编辑器里模糊查询)
44 |
45 | 但总的来说只有一个原因:
46 |
47 | - 实现基于模式查询的自动处理
48 |
49 | 一个经典的正则例子,以千分位切割数字:
50 | 把 ((不是边界、且右边有(3\*n 个数字))的位置),变成逗号。
51 |
52 | ```javascript
53 | const toThousand = (str) =>
54 | String(str).replace(/\B(?=(\d{3})+\b)/g, ',');
55 |
56 | toThousand(123456789); // => "123,456,789"
57 | ```
58 |
59 | ## 学习 正则表达式
60 |
61 | ### 概览
62 |
63 | - 耗时:从入门到掌握需要大约一天
64 | - 难点:记住所有基本规则、断言、合理使用
65 | - 工具:JS 自带的 RegExp,所以任意浏览器 devtool 或 Node 即可
66 |
67 | ### 学习路线
68 |
69 | - 前置学习
70 | - [JavaScript 语言基础(2021)](/cs/javascript-language-basic)
71 | - 学习正则表达式
72 | - 使用 JS 练习所有正则规则
73 | - 了解:不同工具中的正则可能会有一些扩展规则
74 | - 实战
75 | - 在工作业务中使用正则完成代码需求
76 | - 在批量编辑代码时使用正则完成查找(比如 VS Code 中)
77 | - 在其他场景使用正则(如 `sed`、`grep`)
78 | - 进阶(正则迷你书)
79 | - 正则运行原理:非贪婪(惰性)、回溯和性能优化
80 | - NFA DFA 匹配器(回溯陷阱)
81 | - 正则运算符的优先级
82 |
83 | ## 资料
84 |
85 | ### 自学教材
86 |
87 | - 电子教程
88 | - [《JS 正则迷你书》](https://github.com/qdlaoyao/js-regex-mini-book)
89 | - [Learn Regex The Easy Way](https://github.com/ziishaned/learn-regex/blob/master/translations/README-cn.md):中文版
90 | - 书籍
91 | - [JavaScript 高级程序设计](https://book.douban.com/subject/10546125/):(第三版)5.4 RegExp 类型
92 | - [JavaScript 忍者秘籍](https://book.douban.com/subject/26638316/):(第二版)第 10 章(正则)
93 | - 正则的细节
94 | - [正则表达式零宽断言详解](https://www.cnblogs.com/onepixel/articles/7717789.html)
95 | - [Unicode: flag "u" and class \p{...}](https://javascript.info/regexp-unicode)
96 |
97 | ### 在线正则解析(帮助理解)
98 |
99 | - [RegExr](https://regexr.com/):规则解析
100 | - [Regulex](https://jex.im/regulex/):可视化解析
101 |
102 | ### 文档
103 |
104 | - [正则表达式 - MDN](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Regular_Expressions)
105 | - [正则表达式 - javascript.info](https://zh.javascript.info/regular-expressions)
106 |
107 | ## 正则表达式 知识体系
108 |
109 | ### 正则基本概念
110 |
111 | (个人整理和分类,用语可能不太规范,但容易理解)
112 |
113 | - **正则基础规则**
114 | - 正则支持任意朴素字符
115 | - `hello world`
116 | - 正则支持子正则的平行拼接
117 | - `^h(a|e)?llo\sworld\b.*$`
118 | - **字符模式(匹配单个字符)**
119 | - **字符组**
120 | - `[abc]` a 或 b 或 c (匹配这些字符)
121 | - `[^abc]` 不是 a 或 b 或 c 的其他字符(排除这些字符)
122 | - `[a-z]` 匹配 a 到 z
123 | - `[g-zA-F1-5]` 匹配小写 g 到 z、大写 A 到 F、数字 1 到 5
124 | - **转义字符**
125 | - `.` 任意字符
126 | - `\s` 空格
127 | - `\S` 非空格
128 | - `\d` 数字
129 | - `\D` 非数字
130 | - `\w` 字符(字母+数字+下划线)
131 | - `\W` 非字符
132 | - `\t` tab
133 | - `\n` 换行
134 | - `\r` 回车
135 | - `\/` `/`(因为 JS 正则字面量写法以斜杠包裹,所以需要转义。其他具有功能的字符也同理,例如:`/c:\/\[path\]/` => `c:/[path]`)
136 | - **捕获和引用**(括号,可用于后续处理,如 replace)
137 | - **捕获组** `()`
138 | - `(hallo)` 匹配 hallo,且捕获括号内内容
139 | - (捕获组的捕获顺序,按左括号从左到右为 1234…)
140 | - **正则内引用** `\1`
141 | - `(ab),\1` 匹配 'ab,ab'
142 | - **结果引用**(replace 第二参数的特殊字符)
143 | - `$1` 按捕获顺序,例如:`'abcd'.replace(/(ab)/, '$1,') => 'ab,c'`
144 | - `$&` 匹配的整个子串
145 | - `` $` `` 匹配子串的左边文本(键盘左侧的反引号)
146 | - `$'` 匹配子串的右边文本(键盘右侧的引号)
147 | - `$$` 转义 `$`
148 | - **组合模式(正则串的单次组合)**
149 | - **或** `|`
150 | - `h(a|e)llo` 匹配 hallo 或 hello(切换匹配(并捕获))
151 | - **量词**(左边的 a 可以是任意正则模式)
152 | - `a+` 匹配 'a、'aa'(至少一个)
153 | - `a*` 匹配 ''、'aaa'(零或多个)
154 | - `a?` 匹配 ''、'a'(零或一个)
155 | - `a{3}` 匹配 'aaa'(精确的 N 个)
156 | - `a{3,}` 匹配 'aaa' 到 'aaaaaaa...'(至少 N 个)
157 | - `a{3,6}` 匹配 'aaa' 到 'aaaaaa'(N 到 M 个)
158 | - **非贪婪(惰性)**
159 | - `a{3,6}?` 匹配 'aaa'(非贪婪:匹配到越少越好)
160 | - **位置模式(位置不是字符,不具有宽度)**
161 | - **转义字符**
162 | - `^` 行开头
163 | - `$` 行结尾
164 | - `\b` 单词边界
165 | - `\B` 非单词边界
166 | - **断言**(其中的 a 可以是任意子正则)
167 | - `(?=a)` Positive lookahead,右边匹配
168 | - `(?!a)` Negative lookahead,右边不匹配
169 | - `(?<=a)` Positive lookbehind,左边匹配
170 | - `(? ArrayLike | null`
181 | - `reg.test(str) => boolean`
182 | - String
183 | - `str.match(reg) => ArrayLike | null`
184 | - `str.matchAll(reg) => Iterator`
185 | - `str.replace(reg|str, str|fn) => string`
186 | - `str.search(reg) => index | -1`
187 | - `str.split(reg|str, limit?) => array`
188 |
189 | ```javascript
190 | // * -------------------------------- 构造正则
191 |
192 | // * 字面量
193 | var re1 = /foo*/g;
194 |
195 | // * 构造函数(以便支持动态生成)
196 | var re2 = RegExp('foo*', 'g');
197 |
198 | re1 instanceof RegExp; // => true
199 | re2 instanceof RegExp; // => true
200 |
201 | typeof re1; // => "object"
202 | typeof re2; // => "object"
203 |
204 | // * ---------------- flag example: g and u
205 |
206 | '😄🤔'.match(/./gu); // => ["😄", "🤔"]
207 |
208 | // * -------------------------------- RegExp
209 |
210 | /(ba)r*/g.exec('barrrbar');
211 | // => ["barrr", "ba", index: 0, input: "barrrbar", groups: undefined]
212 |
213 | /(ba)r*/g.test('barrrbar');
214 | // => true
215 |
216 | // * -------------------------------- String
217 |
218 | // * ---------------- basic
219 |
220 | 'barrrbar'.match(/(ba)r*/g);
221 | // => ["barrr", "bar"]
222 |
223 | 'barrrbar'.match(/(ba)r*/);
224 | // => ["barrr", "ba", index: 0, input: "barrrbar", groups: undefined]
225 |
226 | 'barrrbar'.search(/(ba)r*/g);
227 | // => 0 (相当于支持正则的 indexOf)
228 |
229 | '2019/12-26'.split(/-|\//);
230 | // => ["2019", "12", "26"]
231 |
232 | // * ---------------- matchAll
233 |
234 | // * matchAll 返回结果是一个 Iterator
235 |
236 | [...'barrrbar'.matchAll(/(ba)r*/g)];
237 |
238 | // => [
239 | // ["barrr", "ba", index: 0, input: "barrrbar", groups: undefined],
240 | // ["bar", "ba", index: 5, input: "barrrbar", groups: undefined]
241 | // ]
242 |
243 | // * ---------------- replace
244 |
245 | 'barrrbar'.replace(/(ba)r*/g, '$1,');
246 | // => "ba,ba,"
247 |
248 | 'reg is not hard'.replace(
249 | /(is|are)\s?(not)?/,
250 | '$1 $2',
251 | );
252 | // => "reg is not hard"
253 |
254 | 'reg is not hard'.replace(/(is|are)(\snot)?/, '$&');
255 | // => "reg is not hard"
256 |
257 | 'reg_is_cool'.replace(/(is|are)/, '$`');
258 | // => "reg_reg__cool"
259 |
260 | 'reg_is_cool'.replace(/(is|are)/, "$'");
261 | // => "reg__cool_cool"
262 |
263 | // * ---------------- replace function
264 |
265 | function replacer(match, p1, p2, p3, offset, string) {
266 | // p1 is nondigits, p2 digits, and p3 non-alphanumerics
267 | return [p1, p2, p3].join(' - ');
268 | }
269 | var newString = 'abc12345#$*%'.replace(
270 | /([^\d]*)(\d*)([^\w]*)/,
271 | replacer,
272 | );
273 | // => "abc - 12345 - #$*%"
274 | ```
275 |
276 | ## 正则表达式 相关
277 |
278 | ### 关于断言的翻译 {#about-regex-assertion-translation}
279 |
280 | 关于断言的主流翻译,我个人认为非常垃圾,
281 | 我之前非常难理解断言的概念,
282 | 现在看来,应该是垃圾翻译造成的:
283 |
284 | - `Positive lookahead` => `零宽正向先行断言`
285 | - `Negative lookahead` => `零宽负向先行断言`
286 | - `Positive lookbehind` => `零宽负向先行断言`
287 | - `Negative lookbehind` => `零宽正向后行断言`
288 |
289 | 嗨,我的老伙计!您瞧瞧,这说的是人话吗?
290 |
291 | `Positive`/`Negative` 翻译成 正向/负向?上下文呢?
292 | 正向的意思是指字符串方向么?
293 |
294 | 实际上,这两个英文单词还有很多意思:
295 |
296 | - Positive:肯定的、确定的、阳性的
297 | - Negative:否定的、拒绝的、阴性的
298 |
299 | 根据正则的用途和实际的规则,
300 | 也就是 **找到**/**找不到**,
301 | 或者说 **应该匹配**/**不应该匹配**。
302 |
303 | 可以发现和 正向/负向 没有半毛钱关系,
304 | 实属垃圾翻译。
305 |
306 | `lookahead`/`lookbehind` => `先行`/`后行`,也可以改进。
307 |
308 | 什么叫先行后行?中文中的“先行”还可以这样用:
309 |
310 | > 茶会尚未结束,它就先行离开了。
311 |
312 | 所以断言里的 `lookhead` 是已经出现的、之前的字符串的意思吗?
313 | 恰恰相反,是指后面的字符串。
314 | 不良的翻译造成了理解的困惑。
315 |
316 | 实际上,英文中有这么一对词组:
317 |
318 | - look ahead:预测、向前看、计划未来
319 | - look behind:回顾、回头看
320 |
321 | 字符串的书写是从左到右的,
322 | 未来,也就是还未出现的,当前位置右边的字符串,
323 | 回顾,也就是已出现的,当前位置左边的字符串。
324 |
325 | 我见过的另一个翻译版本略微高明一点:
326 |
327 | - `零宽度正预测先行断言`
328 | - `零宽度负预测先行断言`
329 | - `零宽度正回顾后发断言`
330 | - `零宽度负回顾后发断言`
331 |
332 | 但是我觉得它也有一些问题:
333 | `正`/`负` 的传达的意思依然不够精确,
334 | `预测先行`/`回顾后发` 相当于翻译了两遍。
335 | (记不记得编码中的 DRY 原则?)
336 |
337 | 所以综上,我个人把它翻译为:
338 |
339 | - **`Positive lookahead` => `预测匹配断言`**
340 | - **`Negative lookahead` => `预测不匹配断言`**
341 | - **`Positive lookbehind` => `回顾匹配断言`**
342 | - **`Negative lookbehind` => `回顾不匹配断言`**
343 |
344 | `预测匹配断言`:
345 | 我来预测现在这个位置之后出现的字符串应该符合某模式,
346 | 预测成功了!那么当前位置是符合正则的。
347 |
348 | 或者在理解上更直白:
349 |
350 | - 右边匹配
351 | - 右边不匹配
352 | - 左边匹配
353 | - 左边不匹配
354 |
355 | `=` 就是匹配,`!` 就是不匹配,
356 | 默认编码顺序是右边,用 `<` 左尖括号来表示左边。
357 |
358 | 这样简单的规则总结不仅更符合编码直觉,
359 | 和断言语法中的助记符也非常对应。
360 |
361 | 我的翻译在“信达雅”上,“雅”先不谈,
362 | 但是“信达”程度应该比什么“零宽正向先行断言”高多了,
363 |
364 | 但是垃圾翻译已经先入为主并普及了,我也没办法,
365 | 那么以后沟通的时候索性直接用英文原文得了。
366 |
367 | (再次说明了看懂一手英文的重要性,以及垃圾二手资料的危害性)
368 |
--------------------------------------------------------------------------------
/docs/note/10.frontend/03.npm/1.introduction-to-npm.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: npm 基本概念和使用
3 | date: 2019-11-10 22:20:59
4 | permalink: /frontend/introduction-to-npm
5 | categories:
6 | - 前端开发
7 | - Node.js
8 | tags:
9 | - Node.js
10 | - npm
11 | ---
12 |
13 | # npm 基本概念和使用
14 |
15 | ## 概览
16 |
17 | - [npm-package.json | npm Documentation](https://docs.npmjs.com/files/package.json)
18 |
19 | 简单开发只需安装一个版本的 `node` 即可,
20 | 多项目开发环境可以利用 `nvm` 进行版本切换。
21 |
22 | 提高 npm 装包的速度,在国内可以使用淘宝源,
23 | 安装 `nrm` 接着 `nrm use taobao` 自动修改配置文件,
24 | 即可达到提速效果,之后像往常一样直接使用 npm。
25 |
26 | ### 常用工具
27 |
28 | - node
29 | - 现代化前端开发基本环境,可在命令行中运行 JS 代码
30 | - Node 偶数版是长期支持版,进度参考官网
31 | - `brew install node`,不过推荐使用 `n` 来安装 node 和做版本控制
32 | - npm
33 | - Node Package Manager,包管理器,node 装好后附带的工具
34 | - `npm i -g npm` 是升级 npm 自己
35 | - n
36 | - Node Version Manager,Node 版本(环境)切换工具
37 | - `brew install n`
38 | - nrm
39 | - Npm Registry Manager,npm 仓库切换器
40 | - `npm i -g nrm --registry=https://registry.npmmirror.com`
41 | - pnpm
42 | - 可代替 npm 的管理器,更快、省空间、monorepo 支持方便
43 | - `npm i -g pnpm`
44 |
45 | ### 基本命令
46 |
47 | ```bash
48 | # 查看版本
49 | node -v
50 | npm -v
51 | pnpm -v
52 |
53 | # nvm
54 | n ls
55 | sudo n lts
56 |
57 | # nrm
58 | nrm ls
59 | nrm use taobao
60 |
61 | # npm
62 | npm i -g typescript # 全局安装
63 | npm init # 新建一个项目
64 | npm i @types/node # 在项目中安装一个包
65 | npm un @types/node # 在项目中卸载一个包
66 | ```
67 |
68 | ## npm 相关概念
69 |
70 | - 同义词
71 | - registry、仓库、源
72 | - package、包
73 |
74 | * [cnpm](https://github.com/cnpm) 是由淘宝开发的一套 npm 生态,包含服务端、客户端、npm 镜像(可视为已配置好的服务端),等等一系列工具和服务。
75 | * [package.json](https://github.com/stereobooster/package.json) 是一个包含 npm package 相应信息的配置文件。
76 |
77 | ### 服务端
78 |
79 | `verdaccio`、`sinopia` 等私有库工具都是属于服务端。
80 | 也有其他 SaaS 形式的服务(比如 [Nexus Repository Manager](https://www.sonatype.com/nexus-repository-sonatype)、[GitHub Package Registry](https://help.github.com/en/articles/configuring-npm-for-use-with-github-package-registry))。
81 |
82 | - [搭建私有 npm 仓库](/frontend/set-up-a-private-npm-registry-using-verdaccio)
83 |
84 | ### 客户端
85 |
86 | - [npm](https://docs.npmjs.com/about-npm/):Node.js 默认的包管理器。
87 | - [pnpm](https://pnpm.io/):可代替 npm,更快、省空间、monorepo 支持方便
88 |
89 | 客户端基本使用方式:
90 |
91 | - `npm i the-answer` / `npm un the-answer`
92 | - `pnpm i the-answer` / `pnpm un the-answer` (保持一致)
93 |
94 | ### registry
95 |
96 | 源、仓库,存放众多开发者所开发的 package 的地方。
97 |
98 | 很多公开源都只是官方 npm 的镜像,
99 | 定期自动同步(只读),并且拒绝接收 package 发布。
100 |
101 | - 官方仓库:https://registry.npmjs.org/
102 | - 淘宝源:https://registry.npm.taobao.org/
103 |
104 | 当我们搭建了私有仓库之后,也就成为了一个可供我们访问的源,
105 | 只需要在客户端配置好地址即可。
106 |
107 | ### registry 的切换方式
108 |
109 | 上文提到的三个客户端都兼容 npm 的配置方式。
110 | 那么下面的例子只列举 npm 的方式,
111 | 也可以将命令中的 npm 替换成 pnpm 查看效果。
112 |
113 | 仓库的切换有以下几种方式。
114 |
115 | #### 通过参数
116 |
117 | 只需要在命令最后加 `--registry=${url}` 参数即可,例如:
118 | `npm i the-answer --registry=https://registry.npm.taobao.org/`
119 |
120 | #### 通过 config
121 |
122 | npm 自带的命令 `config set registry ${url}`,例如:
123 | `npm config set registry https://registry.npm.taobao.org/`
124 | 这个方式避免了每次输相关命令都需要敲入参数。
125 | 输入 `config --help` 看到 config 的命令有 `set, get, delete, list` 等。
126 |
127 | #### 通过 nrm
128 |
129 | config 能够保存配置到全局,但是在切换不同仓库的时候依然过于繁琐。
130 | 有一个工具简化这个过程,就是 [nrm](https://github.com/Pana/nrm)。
131 |
132 | nrm 是 npm registry manager 的缩写,顾名思义,也就是仓库源的管理工具。
133 | 有 `add、del、ls、use、current` 等命令。
134 | 并且自带了一些常用的 npm 源清单。
135 |
136 | 比如可以执行 `nrm use taobao`、`nrm use npm` 在淘宝源和官方仓库之间快速切换。
137 |
138 | 例如使用自己搭建的本地私有仓库:
139 |
140 | ```
141 | nrm add localnpm http://localhost:4873/
142 | nrm use localnpm
143 | ```
144 |
--------------------------------------------------------------------------------
/docs/note/10.frontend/03.npm/2.speeding-up-npm-install.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 用 Proxy 进一步提高 npm 安装速度
3 | date: 2019-11-10 22:20:59
4 | permalink: /frontend/speeding-up-npm-install
5 | categories:
6 | - 前端开发
7 | - Node.js
8 | tags:
9 | - npm
10 | - 命令行
11 | ---
12 |
13 | # 用 Proxy 进一步提高 npm 安装速度
14 |
15 | ## 碰到的问题
16 |
17 | 在前一篇 [Node 概览](/frontend/introduction-to-npm) 中我们提到:
18 | 可以使用换源的方式提高 npm 的安装速度,
19 | `nrm use taobao` 已经足够快。
20 |
21 | 但在安装一些包的时候,还是会表现出假死状态或失败报错。
22 | 例如安装 `node-sass`、`cypress`、`puppeteer` 等。
23 | (用 npm 或 pnpm 或其他工具都有这个问题)
24 |
25 | ## 原因
26 |
27 | 这是网络原因,因为这些包需要从 npm 以外的地址下载数据。
28 | 所以只有 npm 换源起不到作用。
29 |
30 | **node-sass**
31 |
32 | ```bash
33 | $ npm i --save-dev node-sass
34 | ...
35 | > node-sass@4.13.1 install /Users/lc/0Work/temp/test/node_modules/node-sass
36 | > node scripts/install.js
37 |
38 | Downloading binary from https://github.com/sass/node-sass/releases/download/v4.13.1/darwin-x64-79_binding.node
39 | ```
40 |
41 | **cypress**
42 |
43 | ```bash
44 | $ npm i --save-dev cypress
45 | ...
46 | > cypress@4.3.0 postinstall /Users/lc/0Work/temp/test/node_modules/cypress
47 | > node index.js --exec install
48 |
49 | Installing Cypress (version: 4.3.0)
50 |
51 | ⠧ Downloading Cypress
52 | Unzipping Cypress
53 | Finishing Installation
54 | ```
55 |
56 | **puppeteer**
57 |
58 | ```bash
59 | $ npm i --save-dev puppeteer
60 | ...
61 | > puppeteer@2.1.1 install /Users/lc/0Work/temp/test/node_modules/puppeteer
62 | > node install.js
63 |
64 | Downloading Chromium r722234 - 116.4 Mb [ ] 1% 536.9s
65 | ```
66 |
67 | 在这些包的实际文件中,
68 | 也果然能够找到关于下载链接或代理的代码。
69 |
70 | **node-sass**: `node_modules/node-sass/lib/extensions.js`
71 |
72 | ```js
73 | function getBinaryUrl() {
74 | var site =
75 | getArgument('--sass-binary-site') ||
76 | process.env.SASS_BINARY_SITE ||
77 | process.env.npm_config_sass_binary_site ||
78 | (pkg.nodeSassConfig && pkg.nodeSassConfig.binarySite) ||
79 | 'https://github.com/sass/node-sass/releases/download';
80 |
81 | return [site, 'v' + pkg.version, getBinaryName()].join(
82 | '/',
83 | );
84 | }
85 | ```
86 |
87 | **cypress**: `node_modules/cypress/lib/tasks/download.js`
88 |
89 | ```js
90 | var defaultBaseUrl = 'https://download.cypress.io/';
91 |
92 | var getProxyUrl = function getProxyUrl() {
93 | return (
94 | process.env.HTTPS_PROXY ||
95 | process.env.https_proxy ||
96 | process.env.npm_config_https_proxy ||
97 | process.env.HTTP_PROXY ||
98 | process.env.http_proxy ||
99 | process.env.npm_config_proxy ||
100 | null
101 | );
102 | };
103 | ```
104 |
105 | **puppeteer**: `node_modules/puppeteer/lib/BrowserFetcher.js`
106 |
107 | ```js
108 | const DEFAULT_DOWNLOAD_HOST =
109 | 'https://storage.googleapis.com';
110 |
111 | const supportedPlatforms = [
112 | 'mac',
113 | 'linux',
114 | 'win32',
115 | 'win64',
116 | ];
117 | const downloadURLs = {
118 | linux:
119 | '%s/chromium-browser-snapshots/Linux_x64/%d/%s.zip',
120 | mac: '%s/chromium-browser-snapshots/Mac/%d/%s.zip',
121 | win32: '%s/chromium-browser-snapshots/Win/%d/%s.zip',
122 | win64: '%s/chromium-browser-snapshots/Win_x64/%d/%s.zip',
123 | };
124 | ```
125 |
126 | 那么如果环境访问外网太慢或无法访问外网,
127 | 显然就会导致安装太慢或失败。
128 |
129 | ## 解决方法
130 |
131 | 有几个解决方法:
132 |
133 | 一是添加 `--ignore-scripts` 直接无视额外安装脚本,
134 | 例如:`npm i --save-dev node-sass --ignore-scripts`
135 |
136 | 二是使用**对应的镜像源**参数,
137 | 例如:`npm i --save-dev node-sass --sass_binary_site=https://npm.taobao.org/mirrors/node-sass/`
138 |
139 | 这也适用于离线安装的情况,比如指向企业的内网镜像库。
140 |
141 | ## 代理的方法
142 |
143 | 而个人开发的万金油方法,是使用代理连接到高速服务器,
144 | (也可以指向企业的内网镜像库,实现离线安装)
145 |
146 | (以下内容基于 mac,windows 的命令可能不同但原理类似)
147 | 在终端中执行:
148 |
149 | ```bash
150 | export http_proxy="http://127.0.0.1:1080"
151 | ```
152 |
153 | 其中的 `http://127.0.0.1:1080` 是我们配置的一个内网 proxy,
154 | 直接将所有请求转发到(公司的)高速服务器。
155 | (关于 proxy 的配置方式这里不详细说明。)
156 |
157 | 可以在 `~/.zshrc` 里做更详细的处理,
158 | 并把代理封装成两个函数作为快捷开关。
159 | (`bash` 或 `fish` 等其他 `shell` 类似)
160 |
161 | ```bash
162 | export no_proxy=localhost,127.0.0.1,mysite.com # 白名单
163 |
164 | function proxy() {
165 | export http_proxy="http://127.0.0.1:1080" # 改成你自己的地址
166 | export https_proxy="http://127.0.0.1:1080" # 改成你自己的地址
167 | echo "HTTP Proxy on"
168 | }
169 |
170 | function unproxy() {
171 | unset http_proxy https_proxy # 取消 proxy
172 | echo "HTTP Proxy off"
173 | }
174 |
175 | proxy # 可以加入这一行实现打开终端直接开启 proxy
176 | ```
177 |
178 | 这样就生成了 `proxy`、`unproxy` 两个开关代理的方法。
179 | 然后打开新的终端,再尝试安装:
180 |
181 | ```bash
182 | # cd temp/test/
183 | # proxy
184 | npm i --save-dev puppeteer
185 | ```
186 |
187 | 此时外部文件的下载已经通过高速代理,所以不会再卡住安装。
188 |
189 | ```bash
190 | Downloading Chromium r722234 - 116.4 Mb [====== ] 28% 19.7s
191 | ```
192 |
--------------------------------------------------------------------------------
/docs/note/10.frontend/03.npm/3.set-up-a-private-npm-registry-using-verdaccio.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 使用 verdaccio 搭建私有 npm 仓库
3 | date: 2019-11-10 22:20:59
4 | permalink: /frontend/set-up-a-private-npm-registry-using-verdaccio
5 | categories:
6 | - 前端开发
7 | - Node.js
8 | - 前端工具
9 | tags:
10 | - Node.js
11 | - npm
12 | - verdaccio
13 | ---
14 |
15 | # 使用 verdaccio 搭建私有 npm 仓库
16 |
17 | 私有仓库可用于包的开发和发布测试。
18 | 或作为镜像仓库缓存离线使用。
19 |
20 | ## 背景
21 |
22 | ### 基本需求分析
23 |
24 | 私有的 npm 仓库是实现不同项目的代码库共享的方式之一,
25 | 基本需求依次为:
26 |
27 | - 私有仓库
28 | - 可正常使用 npm 的功能
29 | - 小团队使用,避免太过复杂的配置过程
30 | - 私有权限管理
31 |
32 | ### 可选方案
33 |
34 | 经初步调研,有几款工具可以覆盖上述需求。
35 |
36 | - [verdaccio](https://github.com/verdaccio/verdaccio)
37 | - [sinopia](https://github.com/rlidwka/sinopia)
38 | - [cnpm(server)](https://github.com/cnpm/cnpmjs.org)
39 |
40 | cnpm 的实现 [略显复杂](https://cnpmjs.org/),可能不适用于轻度使用;
41 | sinopia 基本已经不再维护(3 years ago);
42 | verdaccio fork 于 sinopia,并且在持续更新。
43 |
44 | 于是对于私有仓库,我们可以尝试 verdaccio。
45 |
46 | 有一些好的特性,不过由于其轻量级的特性,也会有一些不足之处。
47 |
48 | - **Pro**
49 | - 配置简单可控,文档和示例丰富
50 | - 使用本地文件缓存代替 sql,无需配置存储
51 | - 私有的发布访问
52 | - 简单的权限系统
53 | - 图形化管理界面
54 | - 可以同时使用多个源地址
55 | - **Con**
56 | - 一些附加功能不太成熟(比如权限管理之于大型团队)
57 | - 文档中文化程度一般。
58 |
59 | 综合来说,verdaccio 比较适合小团队或个人。
60 |
61 | ### 相关文档
62 |
63 | - [Installation · Verdaccio](https://verdaccio.org/docs/zh-CN/installation)
64 | - [npm-publish | npm Documentation](https://docs.npmjs.com/cli/publish)
65 |
66 | ## 配置 verdaccio
67 |
68 | ### 搭建和配置
69 |
70 | `verdaccio` 虽然是一个私有仓库搭建工具,但本身也是一个基于 `npm` 的包。
71 | 所以需要预先安装 `node` 和 `npm`,接着执行:
72 |
73 | ```shell
74 | # 终端
75 | npm i -g verdaccio # 安装
76 | verdaccio # 启动 verdaccio
77 | ```
78 |
79 | 可以看到 log 信息:
80 |
81 | ```shell
82 | warn --- config file - /Users/lc/.config/verdaccio/config.yaml
83 | warn --- Plugin successfully loaded: htpasswd
84 | warn --- Plugin successfully loaded: audit
85 | warn --- http address - http://localhost:4873/ - verdaccio/3.11.5
86 | ```
87 |
88 | 说明已经启动成功,可以看到仓库的默认地址是 `http://localhost:4873/`
89 | 配置文件在 `~/.config/verdaccio/config.yaml`
90 | 并且在浏览器中访问 ,可以看到一个图形化管理界面。
91 | verdaccio 可以设置多个源,我们加入淘宝源。
92 | (也可以直接删掉 npmjs 相应的行,只使用淘宝源,以提高响应速度。)
93 |
94 | ```yaml
95 | # config.yaml
96 | uplinks:
97 | npmjs:
98 | url: https://registry.npmjs.org/
99 | # 其他设置 ...
100 | taobao:
101 | url: https://registry.npm.taobao.org/
102 | # 其他设置 ...
103 | # 其他设置 ...
104 | packages:
105 | '@*/*':
106 | proxy:
107 | - npmjs
108 | - taobao
109 | # 其他设置 ...
110 | '**':
111 | proxy:
112 | - npmjs
113 | - taobao
114 | # 其他设置 ...
115 | ```
116 |
117 | 设置完成后,保存并重启命令行中的 verdaccio。
118 | 保持 verdaccio 的运行状态,打开新的终端窗口备用。
119 |
120 | ### set registry
121 |
122 | 我们先将 npm registry 改为这个地址:
123 |
124 | ```shell
125 | # npm config
126 | npm config set registry http://localhost:4873/
127 | npm config get registry # -> http://localhost:4873/
128 |
129 | # 或 nrm
130 | nrm add localnpm http://localhost:4873/
131 | nrm use localnpm
132 | ```
133 |
134 | ### npm install
135 |
136 | 测试对于现有包的安装是否正常,建立一个空项目,安装 `the-answer` 这个包。
137 |
138 | ```shell
139 | mkdir test-localnpm
140 | cd test-localnpm
141 | npm init -y
142 | npm i the-answer # 安装 the-answer
143 | ```
144 |
145 | 回到运行 verdaccio 的终端窗口可以看到一下内容,
146 | 说明 verdaccio 从多个源获取包信息,并传回 npm 客户端。
147 |
148 | ```shell
149 | http --> 200, req: 'GET https://registry.npm.taobao.org/the-answer' (streaming)
150 | http --> 200, req: 'GET https://registry.npm.taobao.org/the-answer', bytes: 0/2632
151 | http --> 200, req: 'GET https://registry.npmjs.org/the-answer' (streaming)
152 | http --> 200, req: 'GET https://registry.npmjs.org/the-answer', bytes: 0/2661
153 | http <-- 200, user: null(127.0.0.1), req: 'GET /the-answer', bytes: 0/1122
154 | http <-- 200, user: null(127.0.0.1), req: 'GET /the-answer', bytes: 0/1122
155 | ```
156 |
157 | 而重新安装或全新安装的 log 则会变成:
158 |
159 | ```shell
160 | http <-- 304, user: null(127.0.0.1), req: 'GET /the-answer', bytes: 0/0
161 | http <-- 304, user: null(127.0.0.1), req: 'GET /the-answer', bytes: 0/0
162 | ```
163 |
164 | ```shell
165 | http --> 304, req: 'GET https://registry.npm.taobao.org/the-answer' (streaming)
166 | http --> 304, req: 'GET https://registry.npm.taobao.org/the-answer', bytes: 0/0
167 | http --> 304, req: 'GET https://registry.npmjs.org/the-answer' (streaming)
168 | http --> 304, req: 'GET https://registry.npmjs.org/the-answer', bytes: 0/0
169 | http <-- 200, user: null(127.0.0.1), req: 'GET /the-answer', bytes: 0/1122
170 | http <-- 200, user: null(127.0.0.1), req: 'GET /the-answer', bytes: 0/1122
171 | ```
172 |
173 | 一些地方的 http status 从 200 变成了 304,
174 | 表示有缓存功能的存在,不会每次都重新从远端仓库下载包代码。
175 | 尝试在代码中调用,可以发现 `the-answer` 这个包能够正常工作。
176 |
177 | ```javascript
178 | // .js
179 | const theAnswer = require('the-answer');
180 | console.log(theAnswer); // -> 42
181 | ```
182 |
183 | ### 包的发布
184 |
185 | 具体流程和 npm 官方一致。
186 | (只不过现在仓库地址指向我们建立的私有仓库,可以更自由地进行实验。)
187 |
188 | 下面简单重现一下使用步骤。
189 | (详细步骤可参考[这篇文章](https://www.jianshu.com/p/36d3e0e00157))
190 |
191 | #### 开发一个 package
192 |
193 | 建立一个新的目录用以开发一个新的 package。
194 |
195 | ```bash
196 | mkdir test-lib-local
197 | cd test-lib-local
198 | npm init -y
199 | ```
200 |
201 | 可以看到 `package.json` 中默认有 `"main": "index.js"`,
202 | 表示 cjs 规范中的文件入口。
203 | 那么(新建这个文件并)添加简单代码:
204 |
205 | ```javascript
206 | // index.js
207 | module.exports = 'check1234';
208 | ```
209 |
210 | #### 发布这个 package
211 |
212 | 执行 `npm adduser`(或 alias `npm login`)登录,
213 | 执行 `npm publish` 发布。
214 | 如果控制台看到以下信息,则说明发布成功。
215 |
216 | ```shell
217 | npm notice
218 | + test-lib-local@1.0.0
219 | ```
220 |
221 | #### 调用这个 package
222 |
223 | 参考之前的章节,建立新的项目、链接到本地仓库,并安装我们新发布的包:
224 | `npm i test-lib-local`
225 | 测试安装是否正常:
226 |
227 | ```javascript
228 | // .js
229 | const lib = require('test-lib-local');
230 | console.log(lib); // -> 'check1234'
231 | ```
232 |
233 | 此时可以切换回官方仓库看看,再进行安装应该是不成功的,
234 | 因为我们的包发布在私有仓库中,并不是在官方仓库中。
235 |
236 | ### 权限管理
237 |
238 | verdaccio 的权限管理(以及注册登录等等)功能目前还是比简单的。
239 | 并且不支持用户分组,可配置程度相比 cnpm 要弱。
240 | 也没有设计接口,只能通过修改配置文件并重启程序的方式刷新。
241 |
242 | ```yaml
243 | packages:
244 | '@my-custom-lib/*':
245 | access: username1
246 | publish: username1
247 | # 其他设置 ...
248 | '**':
249 | access: $all
250 | publish: $authenticated
251 | # 其他设置 ...
252 | ```
253 |
--------------------------------------------------------------------------------
/docs/note/10.frontend/04.react/1.react-hooks.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: React Hooks 学习指南
3 | date: 2019-11-17 13:17:17
4 | permalink: /frontend/react-hooks
5 | categories:
6 | - 前端开发
7 | - 前端工具
8 | tags:
9 | - react
10 | ---
11 |
12 | # React Hooks 学习指南
13 |
14 | ## Hooks 简介
15 |
16 | ### 什么是 React Hooks
17 |
18 | > Hooks 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。
19 |
20 | 换句话说:只用函数 + Hooks 来完成组件编写。
21 |
22 | Hooks 隐藏了 Class 写法中生命周期的概念,
23 | 或者说 React 自己尽量帮你处理了生命周期。
24 |
25 | ### 为什么要用 Hooks
26 |
27 | 如果你喜欢写 FP 而不是 OOP 风格的代码,
28 | 那么你可能早就开始用函数来写 Presentational Components 了。
29 |
30 | 但是函数组件有自己的局限性,
31 | 而 Hooks 突破了函数组件的局限性,
32 | 实现了一些 Class 组件才有的功能。
33 |
34 | ## 学习 Hooks
35 |
36 | ### 概览
37 |
38 | - 耗时:从入门到熟悉需要大约 10~20 小时(个人估计)
39 | - 难点:
40 | - 理解 FP 范式(并知道 Hooks 并不是纯 FP)
41 | - 理解 JS 执行原理
42 | - 探索最佳实践
43 | - 工具:
44 | - [react@16.8+](https://www.npmjs.com/package/react)
45 | - `webpack/parcel/cli`
46 |
47 | ### 学习路线
48 |
49 | - 前置学习
50 | - 理解 functional programming
51 | - side effect
52 | - [JavaScript 进阶指南](/frontend/javascript-advanced)
53 | - 了解 React 基本概念
54 | - 理解 展示组件、容器组件 的区别
55 | - 学习 Context 的特性
56 | - 学习 Hooks
57 | - 练习所有 React 自带的基本 Hooks API
58 | - 结合 TypeScript
59 | - 了解下 react-use(社区 Hooks)
60 | - 对比 Hooks 和 Class 写法的异同
61 | - 实战
62 | - 敲点小型应用 Demo
63 | - 结合 redux/rxjs
64 | - 进阶
65 | - 编写自己的 custom hooks
66 | - 阅读 Hooks 相关源码
67 | - 迷思
68 | - useEffect 的作用和运用
69 | - 探索最佳实践
70 |
71 | ## 资料
72 |
73 | ### 我的学习代码
74 |
75 | - [React - Learn By Doing](https://github.com/seognil-study/learn-by-doing/tree/master/react)
76 |
77 | ### 自学教材
78 |
79 | - [Hooks API 索引](https://zh-hans.reactjs.org/docs/hooks-reference.html)
80 | - [How to useContext in React? - RWieruch](https://www.robinwieruch.de/react-usecontext-hook)
81 | - [【译】什么时候使用 useMemo 和 useCallback](https://jancat.github.io/post/2019/translation-usememo-and-usecallback/)
82 | - [如何錯誤地使用 React hooks useCallback 來保存相同的 function instance](https://medium.com/@as790726/%E5%A6%82%E4%BD%95%E9%8C%AF%E8%AA%A4%E5%9C%B0%E4%BD%BF%E7%94%A8-react-hooks-usecallback-%E4%BE%86%E4%BF%9D%E5%AD%98%E7%9B%B8%E5%90%8C%E7%9A%84-function-instance-7744984bb0a6)
83 |
84 | ### 实战
85 |
86 | - [示例 - React](https://zh-hans.reactjs.org/community/examples.html)
87 | - [react-use](https://github.com/streamich/react-use)
88 |
89 | ### 进阶
90 |
91 | - [React Hooks in TypeScript](https://medium.com/@jrwebdev/react-hooks-in-typescript-88fce7001d0d)
92 | - [useEffect 完整指南](https://overreacted.io/zh-hans/a-complete-guide-to-useeffect/)
93 | - [useEffect vs. useLayoutEffect in plain, approachable language](https://blog.logrocket.com/useeffect-vs-uselayouteffect/)
94 | - [精读《React Hooks 最佳实践》](https://zhuanlan.zhihu.com/p/81752821)
95 | - [精读《怎么用 React Hooks 造轮子》](https://github.com/dt-fe/weekly/blob/v2/080.%E7%B2%BE%E8%AF%BB%E3%80%8A%E6%80%8E%E4%B9%88%E7%94%A8%20React%20Hooks%20%E9%80%A0%E8%BD%AE%E5%AD%90%E3%80%8B.md)
96 |
97 | ### 扩展阅读
98 |
99 | - [V8 将为 React hooks 改进数组解构的性能](https://zhuanlan.zhihu.com/p/49077183)
100 |
101 | ## Hooks 知识体系
102 |
103 | ### Hooks 主要概念
104 |
105 | Hooks 主要是 `useXXX` 系列 API,
106 | 以及实现 Hooks 机制的 React 内部代码(resolveDispatcher 等)。
107 |
108 | - 常用 API
109 | - useContext
110 | - useState
111 | - useReducer
112 | - useRef
113 | - useEffect
114 | - useLayoutEffect
115 | - useCallback
116 | - useMemo
117 |
118 | 另外社区中还衍生出了更多 API:[react-use](https://github.com/streamich/react-use)
119 |
120 | ## Hooks 典型代码
121 |
122 | ### Hooks 大致用法
123 |
124 | - useState
125 | ```javascript
126 | const Comp = () => {
127 | const [state, setState] = useState(initialState)
128 | const handler = (e) => setState(newState || prevState => nextState)
129 | return {state.myKey}
130 | }
131 | ```
132 | - useReducer
133 | ```javascript
134 | const Comp = () => {
135 | const [state, dispatch] = useReducer(
136 | reducer,
137 | initialState,
138 | );
139 | return (
140 | dispatch(action)}>
141 | {state.myKey}
142 |
143 | );
144 | };
145 | ```
146 | - useCallback
147 | ```javascript
148 | const Comp = () => {
149 | const sameFn = useCallback(fn, [byDeps]);
150 | return sameFn()}>
;
151 | };
152 | ```
153 | - useMemo
154 | ```javascript
155 | const Comp = () => {
156 | const sameResult = useMemo(fn, [byDeps]);
157 | return {sameResult}
;
158 | };
159 | ```
160 | - useContext
161 | ```javascript
162 | const MyContext = createContext(null);
163 | const Comp = () => {
164 | const color = useContext(MyContext);
165 | return Hello World
;
166 | };
167 | const App = () => (
168 |
169 |
170 |
171 | );
172 | ```
173 | - useRef
174 | ```javascript
175 | const Comp = () => {
176 | const refer = useRef(null);
177 | return (
178 | refer.current.innerHTML}
181 | >
182 | );
183 | };
184 | ```
185 | - useEffect
186 | ```javascript
187 | const Comp = () => {
188 | const sideEffectFn = () => {
189 | myLogic();
190 | return cancelSideEffectFn();
191 | };
192 | useEffect(sideEffectFn, [byDeps]);
193 | return ;
194 | };
195 | ```
196 | - useLayoutEffect
197 | ```javascript
198 | const Comp = () => {
199 | const sideEffectFn = () => {
200 | myDOMLogic();
201 | return cancelSideEffectFn();
202 | };
203 | useLayoutEffect(sideEffectFn, [byDeps]);
204 | return ;
205 | };
206 | ```
207 | - useImperativeHandle
208 | ```javascript
209 | const ChildInput = forwardRef((props, parentRef) => {
210 | const realRef = useRef(null);
211 | useImperativeHandle(parentRef, () => realRef.current);
212 | return (
213 |
214 | );
215 | });
216 | ```
217 |
218 | ## Hooks 相关
219 |
220 | ### 使用上的注意点
221 |
222 | - 函数组件,在函数体中使用 Hooks API。
223 | - 为了表现出清晰的逻辑,Hooks 最好在函数代码的顶层结构中使用。
224 |
225 | ### Hooks 大致原理
226 |
227 | > 代码没有黑魔法
228 |
229 | 以 useState 为例,直接追踪代码关系(删减了部分细节代码)
230 |
231 | ```javascript
232 | // in 'react'
233 | function useState(initialState) {
234 | var dispatcher = resolveDispatcher();
235 | return dispatcher.useState(initialState);
236 | }
237 |
238 | function resolveDispatcher() {
239 | return ReactCurrentDispatcher.current;
240 | }
241 |
242 | // in 'react-dom'
243 | HooksDispatcherOnMount = {
244 | useState: function (initialState) {
245 | return mountState(initialState);
246 | },
247 | };
248 | HooksDispatcherOnUpdate = {
249 | useState: function (initialState) {
250 | return updateState(initialState);
251 | },
252 | };
253 | ```
254 |
255 | 观察代码可以发现:
256 | `dispatcher` 是 React 提供和维护的一个公共对象,
257 | React 会在不同生命周期(`mount`、`update`)提供不同的 `dispatcher`,
258 | 而不同的 `dispatcher` 包含不同的(相应的)处理方法。
259 |
260 | 函数组件代码中看上去调用了同一个 Hooks API,
261 | 但实际上会在不同时期取到不同的方法,
262 | 也就实现了以前 Class 写法中的生命周期的效果。
263 |
264 | ### Hooks 和 Class 的差异
265 |
266 | Hooks 写法和之前的 Class 写法算是截然不同的范式。
267 |
268 | Runtime 层面的直观差异是:
269 |
270 | - Hooks 组件每次渲染时,函数内可能所有东西都是重新声明的。
271 | (比如依赖 `setState` 的简单的 `onClickHandler`)
272 | - Class 组件,`render()` 中的局部方法一般都指向原型上的同一个,不会重新声明。
273 |
274 | 这算是在内存和性能上的差异(注意不是好坏)。
275 |
276 | 根据这一状况,
277 | Hooks API 自带了一些简单的优化措施(如 第二参数)
278 |
279 | ### 第二参数和优化
280 |
281 | - useEffect
282 | - useCallback
283 | - useMemo
284 |
285 | 以上方法都有第二个可选参数,用作依赖对比,目的是减少重复执行。
286 | 但是,依赖对比也需要一定的计算开销(在 React 内部,至少也有十来行)。
287 |
288 | 所以理解 JS 执行原理并加以权衡,
289 | 单行的简单 `onClickSetStateHandler` 可以不包裹到 `useCallback` 里。
290 |
291 | 可以只在以下情况使用 `useCallback`:
292 |
293 | - 避免重复执行
294 | - 需要同一个函数(如 timer)
295 | - 缓存大开销的函数(如 fetch)
296 |
297 | 也可以根据团队标准全部使用 `useCallback`,降低心智负担。
298 |
299 | ### Hooks 的运用
300 |
301 | 随着 Hooks 的普及和社区的发展,
302 | 函数组件能做的事情越来越多了,
303 | 甚至可以尝试只使用函数组件来写整个应用。
304 |
305 | 对于大型前端软件来说,也可以采取以下方案:
306 |
307 | - 直接由更专业的外部工具(如 redux、rxjs、ramda)
308 | 来处理复杂逻辑业务(如 sideEffect 实体、fetch 竞态、memo 计算)
309 | - React 只负责渲染相关逻辑
310 |
311 | 这样也就不用太关心 Hooks 本身的优化技巧了。
312 |
313 | 需要根据实际情况灵活运用。
314 |
--------------------------------------------------------------------------------
/docs/note/10.frontend/05.state-management/3.rxjs.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: RxJS 学习指南
3 | date: 2019-11-07 21:10:43
4 | permalink: /frontend/rxjs
5 | categories:
6 | - 前端开发
7 | - 前端工具
8 | tags:
9 | - rxjs
10 | ---
11 |
12 | # RxJS 学习指南
13 |
14 | ## RxJS 简介
15 |
16 | ### 什么是 ReactiveX
17 |
18 | ReactiveX 是一组采用响应式流的异步编程 API 标准,不同语言下都有实现了该 API 的具体库,例如 RxJS、RxJava、RxSwift 等。
19 | 它的核心思想是,将离散的**多个事件**视为**一个流**来操控,流可以(通过操作符)进行各种变换(映射、采样、合并等)。
20 |
21 | ### 什么是 RxJS
22 |
23 | RxJS 是 ReactiveX 的 JS 版实现,RxJS 之于事件处理,相当于 Lodash 之于数据处理。
24 |
25 | RxJS 在 Angular 中作为重要的数据底层,但是其本身是一个独立的库,可以在其他场景下使用,例如配合 React + Observable-hooks 作为全局状态管理器。
26 |
27 | ### 为什么要用 RxJS
28 |
29 | 能够更方便地梳理和管控异步逻辑。
30 |
31 | ## 学习 RxJS
32 |
33 | ### 概览
34 |
35 | - 耗时:从入门到熟悉需要大约 15~30 小时
36 | - 难点:
37 | - 理解 Stream 范式
38 | - 熟悉 API 全貌并综合运用
39 | - 工具:
40 | - [rxjs](https://github.com/ReactiveX/rxjs)
41 | - [observable-hooks](https://github.com/crimx/observable-hooks)(for React hooks)
42 |
43 | ### 学习路线
44 |
45 | - 前置学习
46 | - 理解 RxJS 的编程理念
47 | - 编程范式
48 | - [Functional Programming](/cs/introduction-to-functional-programming)
49 | - Reactive Programming
50 | - Stream Programming
51 | - 设计模式
52 | - 观察者模式(事件绑定机制)
53 | - 迭代器模式(事件流的遍历机制)
54 | - ([TypeScript](/cs/typescript-language-basic))
55 | - 学习 RxJS
56 | - 掌握 RxJS 核心概念
57 | - Observable 及其上下游
58 | - 多播操作符、Subject
59 | - Scheduler
60 | - 尝试 RxJS 所有(类型)的 API
61 | - 同类 API 之间的效果差异
62 | - 相同效果的流可以有多种实现方式
63 | - 题目/实战
64 | - 练习实现具体功能,加深理解
65 | - 结合 React/Vue 在项目中使用
66 | - 进阶
67 | - 实现一个自己的 Observable
68 | - 阅读 RxJS 源码实现
69 | - 迷思
70 | - 如何手动结束/关闭一个 Observable
71 | - 内存管理和垃圾回收
72 |
73 | ## 资料
74 |
75 | ### 我的学习代码
76 |
77 | - [RxJs - Learn By Doing](https://github.com/seognil-study/learn-by-doing/tree/master/rxjs)
78 |
79 | ### 关于 响应式编程 的扩展阅读
80 |
81 | - [Introduction to Reactive Programming](https://egghead.io/courses/introduction-to-reactive-programming)
82 | - [The introduction to Reactive Programming you've been missing](https://gist.github.com/staltz/868e7e9bc2a7b8c1f754)
83 | - [RxJS 入门指引和初步应用](https://zhuanlan.zhihu.com/p/25383159)
84 | - [RxJS-响应式流编程](http://blueskyawen.com/2017/12/24/rxjs/)
85 | - [流动的数据——使用 RxJS 构造复杂单页应用的数据逻辑](https://github.com/xufei/blog/issues/38)
86 |
87 | ### RxJS 自学教材
88 |
89 | - 教程
90 | - [Top Ten RxJS Concepts](https://fireship.io/lessons/rxjs-basic-pro-tips/):一些基本概念和 API 的示例
91 | - [Learn RxJS](https://www.learnrxjs.io/) :非常完整的 RxJS 教程站点,涵盖了大部分 API ,有代码片段及小型 Demo
92 | - [RxJS - Introduction](https://rxjs-dev.firebaseapp.com/guide/overview):官方文档教程板块
93 | - 动画/演示/Demo
94 | - [Launchpad for RxJS](https://reactive.how/rxjs/) :(v6)动画演示(一部分),API 按类型整理划分
95 | - [RxJS example + marble diagram](https://thinkrx.io/rxjs/interval/) :(v6)通过代码生成的弹珠台
96 | - [RxJS Marbles](https://rxmarbles.com/) :弹珠台,可直接拖动,只有动画
97 | - 书籍
98 | - [深入浅出 RxJS](https://book.douban.com/subject/30217949/) (v5)
99 |
100 | ### 实战
101 |
102 | - [Recipes - Learn RxJS](https://www.learnrxjs.io/recipes/):Learn RxJS 中的 Demo 板块
103 | - [我所了解的 RxJS](https://juejin.im/post/5ca56f42f265da30982748e6#heading-13)
104 |
105 | ## RxJS 知识体系
106 |
107 | ### RxJS 主要概念
108 |
109 | - **Observable**
110 | - Observable: stream 序列;有多种创建方式,例如 `timer`、`fromEvent` 等
111 | - operator: 操作符,对 Observable 进行形变;例如 `map`、`merge` 等
112 | - **subscribe**
113 | - subscribe: 订阅(Observable 的方法)
114 | - Observer: 观察者/消费者方法集合(业务方法,传给 subscribe() 的)
115 | - subscription: 订阅关系(subscribe 函数返回的对象)
116 | - unsubscribe: 结束订阅方法(Subscription 提供的)
117 | - **Subject**: 多播的 Observable(可以作为 Observable 和 Subscription 的一个胶水层)
118 | - **Scheduler**:调度器,用来调整事件触发的策略,例如 `asyncScheduler`、`animationFrameScheduler` (见名知意)
119 |
120 | * Cold vs Hot Observable
121 | - Cold:多次订阅产生多个独立的事件流(用途例如:`interval`)
122 | - Hot:多次订阅共享同一个事件流(用途例如:`fromEvent`、`Subject`)
123 |
124 | ## RxJS 典型代码
125 |
126 | ### RxJS 基本用法
127 |
128 | #### 伪代码
129 |
130 | ```javascript
131 | // * -------- 新建一个 Observable
132 |
133 | Ob = Observable()
134 | // * (可选)通过不同的操作符对原始 stream 进行加工处理
135 | .pipe(
136 | map((a) => b),
137 | filter((b) => b > 0),
138 | debounceTime(200),
139 | );
140 |
141 | // * -------- 订阅 (以及多种传参方式)
142 |
143 | Subscription = Ob.subscribe((v) => {});
144 |
145 | Subscription = Ob.subscribe(
146 | (v) => {},
147 | (e) => {},
148 | () => {},
149 | );
150 |
151 | Subscription = Ob.subscribe({
152 | next(v) {},
153 | error(e) {},
154 | complete() {},
155 | });
156 |
157 | // * -------- 取消订阅
158 |
159 | Subscription.unsubscribe();
160 | ```
161 |
162 | #### 具体代码 v5
163 |
164 | ```javascript
165 | // Node.js
166 |
167 | import { Observable } from 'rxjs';
168 |
169 | const ob$ = Observable.interval(500).map((e) => e * 2);
170 |
171 | const sub$ = ob$.subscribe((e) => console.warn(e));
172 |
173 | setTimeout(() => sub$.unsubscribe(), 3000);
174 | ```
175 |
176 | #### 具体代码 v6
177 |
178 | ```javascript
179 | // Node.js
180 |
181 | import { interval } from 'rxjs';
182 | import { map } from 'rxjs/operators';
183 |
184 | const ob$ = interval(500).pipe(map((e) => e * 2));
185 |
186 | const sub$ = ob$.subscribe((e) => console.warn(e));
187 |
188 | setTimeout(() => sub$.unsubscribe(), 3000);
189 | ```
190 |
191 | ### RxJS 实用代码
192 |
193 | ```javascript
194 | // * interval of requestAnimationFrame, tick frame time (ms)
195 | const rafInterval$ = () =>
196 | of(Date.now(), animationFrameScheduler).pipe(
197 | map((start) => Date.now() - start),
198 | repeat(),
199 | );
200 | ```
201 |
202 | ## RxJS 相关
203 |
204 | ### RxJS 和 TypeScript
205 |
206 | RxJS 源码是 TypeScript 写的,对 TS 支援度很不错
207 |
208 | 但目前还有些未完美覆盖的情况,例如:
209 |
210 | ```typescript
211 | // * 没有正确识别
212 | pipe(publish()); // => Observable
213 |
214 | // * 需要手动指定 type
215 | pipe(publish()) as ConnectableObservable;
216 | ```
217 |
218 | - [Pipe operator cannot infer return type as ConnectableObservable #2972](https://github.com/ReactiveX/rxjs/issues/2972)
219 | - [Property 'connect' does not exist on type 'Observable\' | RXJS multicast](https://stackoverflow.com/questions/54265143/property-connect-does-not-exist-on-type-observableany-rxjs-multicast)
220 |
221 | ### RxJS 版本
222 |
223 | 截稿时 RxJS 最新的版本是 `v6`
224 | (`v7` 处于 alpha 中)
225 | `v6` 和 `v5` 的主要差别在于 API 名和语法
226 |
227 | 比如为了实现函数式调用风格,
228 | 操作符 `do` 重命名成了 `tap` (因为 `do` 是 JS 保留字)
229 |
230 | 新项目直接用 `v6` 即可
231 | 老项目也可以用兼容包升级
232 |
233 | - [RxJS v5.x to v6 Update Guide](https://rxjs-dev.firebaseapp.com/guide/v6/migration)
234 | - [rxjs CHANGELOG](https://github.com/ReactiveX/rxjs/blob/master/CHANGELOG.md)
235 |
236 | ### 命名习惯
237 |
238 | ```javascript
239 | const myStream$ = interval(500);
240 | ```
241 |
242 | Stream 相关的命名一般用 `$` 做后缀,是一种共识,但也没有硬性规定。
243 | (就像使用 `jQuery` 会用 `$` 作为变量前缀一样)
244 |
--------------------------------------------------------------------------------
/docs/note/10.frontend/08.javascript-test/4.cypress.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Cypress 学习指南
3 | date: 2020-01-29 20:31:10
4 | permalink: /frontend/cypress
5 | categories:
6 | - 前端开发
7 | - 前端工具
8 | tags:
9 | - cypress
10 | ---
11 |
12 | # Cypress 学习指南
13 |
14 | ## Cypress 简介
15 |
16 | ### 什么是 Cypress
17 |
18 | 一个前端测试工具
19 |
20 | - Cypress 能测试什么
21 | - - E2E 测试
22 | - 集成测试
23 | - 单元测试(因为内嵌了 Mocha)
24 | - 任何在浏览器中运行的内容
25 |
26 | * Cypress 提供的一些功能
27 | - 时间旅行
28 | - 自动等待(类似 Jest 中的 wait)
29 | - 以同步风格的代码完成异步操作
30 | - 网络流量控制
31 | - 截屏
32 | - 持续集成
33 |
34 | - Cypress 语法设计(及内置对象)
35 | - jQuery + 链式调用
36 | - Promise(Bluebird)
37 | - Mocha + Chai
38 |
39 | ### 为什么要用 Cypress
40 |
41 | - 当你需要 E2E 测试
42 | - 在 [2019 年 JavaScript 明星项目](https://risingstars.js.org/2019/zh#section-test-framework) 的测试分类中位于第二名
43 | - 比其他同类 E2E 测试工具更简单、灵活、健壮
44 |
45 | ## 学习 Cypress
46 |
47 | ### 概览
48 |
49 | - 耗时:从入门到熟悉基本概念,大约需要 8~16 小时
50 | - 难点:充分利用需要花一定时间学习和配置(报告、覆盖率、CI 等)
51 | - 工具:[cypress](https://docs.cypress.io/guides/getting-started/installing-cypress)
52 |
53 | ### 学习路线
54 |
55 | - 前置学习
56 | - [前端开发入门指南](/note/frontend-development-cookbook)
57 | - ([Jest](/frontend/jest))
58 | - (有一定实际应用开发经验)
59 | - 学习 Cypress
60 | - 了解 Cypress 的组成,全面阅读文档
61 | - 掌握基本使用
62 | - 实战
63 | - 在业务中编写测试
64 | - 进一步熟悉各 API 的大量细节
65 | - 为项目调整 Cypress 配置,使用高级功能
66 |
67 | ## 资料
68 |
69 | ### 自学教材
70 |
71 | - [Cypress End-to-End Testing](https://www.youtube.com/watch?v=7N63cMKosIE):10 分钟,Cypress 概览
72 | - [Cypress 官方文档](https://docs.cypress.io/guides/overview/why-cypress.html#In-a-nutshell)
73 | - [API](https://docs.cypress.io/api/api/table-of-contents.html)
74 | - [最佳实践](https://docs.cypress.io/guides/references/best-practices.html)
75 |
76 | ### 实战
77 |
78 | - [Cypress - Learn By Doing](https://github.com/seognil-study/learn-by-doing/tree/master/testing/cypress)
79 | - [cypress-example-recipes](https://github.com/cypress-io/cypress-example-recipes)
80 |
81 | ## Cypress 知识体系
82 |
83 | ### Cypress 概览
84 |
85 | #### 安装/初始化
86 |
87 | ```bash
88 | # 在已有项目中安装 cypress
89 | npm install cypress --save-dev
90 |
91 | # 接着运行这个命令,cypress 将初始化并生成一堆用例
92 | npx cypress open
93 | ```
94 |
95 | #### [文件结构](https://docs.cypress.io/guides/core-concepts/writing-and-organizing-tests.html#Folder-Structure)
96 |
97 | - **/cypress**
98 | - **/fixtures** (mock 数据)
99 | - example.json
100 | - **/integration** (测试文件)
101 | - **/examples**
102 | - example.spec.js (一般格式为 `*.spec.js`)
103 | - **/plugins** (用于配置安装的 [插件](https://docs.cypress.io/guides/tooling/plugins-guide.html),task 系统)
104 | - index.js
105 | - **/support** (用于调整 [自定义选项](https://docs.cypress.io/guides/references/configuration.html))
106 | - commands.js
107 | - index.js
108 | - /screenshots (默认截屏文件夹)
109 | - **cypress.json**
110 |
111 | #### 测试文件 典型代码
112 |
113 | ```typescript
114 | ///
115 |
116 | describe('描述', () => {
117 | before(() => console.log('---- Test Start! ----'));
118 | beforeEach(() => cy.visit('https://witch.url'));
119 | afterEach(() => cy.clearCookies());
120 |
121 | it('测试用户交互', () => {
122 | cy.get('#app').children('.intro').click();
123 | cy.contains('Welcome').should('be.exist');
124 | });
125 |
126 | it('测试显示文本', () => {
127 | cy.get('div').should('have.text', 'Hello');
128 | // * 另一种风格
129 | cy.get('div').should(($div) => {
130 | const text = $div.text();
131 | expect(text).to.match(/hello/i);
132 | });
133 | });
134 | });
135 | ```
136 |
137 | 大致分为几个部分
138 |
139 | - TypeScript 自动完成支持(第一行的注释)
140 | - 运行器和生命周期(`describe`、`it`、`before` 等)
141 | - 元素查找和操作(`cy` 相关命令)
142 | - 断言/测试(`should`、`expect`、`assert` 多种风格)
143 |
144 | #### Cypress 对象
145 |
146 | [`Cypress` 和 `cy` 的区别](https://docs.cypress.io/api/events/catalog-of-events.html#Cypress)
147 |
148 | - `Cypress`:全局对象,影响所有测试
149 | - [内置工具](https://docs.cypress.io/api/utilities/_.html)
150 | - [`Cypress._`](https://docs.cypress.io/api/utilities/_.html#Syntax):[Lodash](https://lodash.com/)
151 | - [`Cypress.$`](https://docs.cypress.io/api/utilities/$.html):[jQuery](https://jquery.com/)
152 | - [`Cypress.Blob`](https://docs.cypress.io/api/utilities/blob.html):[blob-utli](https://github.com/nolanlawson/blob-util)
153 | - [`Cypress.minimatch()`](https://docs.cypress.io/api/utilities/minimatch.html):[minimatch](https://github.com/isaacs/minimatch)
154 | - [`new Cypress.Promise(fn)`](https://docs.cypress.io/api/utilities/promise.html):[Bluebird](https://github.com/petkaantonov/bluebird)
155 | - [全局 API](https://docs.cypress.io/api/cypress-api/custom-commands.html)
156 | - `cy`:在每个测试中相互独立
157 | - [测试命令](https://docs.cypress.io/api/commands/and.html)
158 |
159 | ### 测试/断言
160 |
161 | [Cypress 中内置的断言](https://docs.cypress.io/guides/references/assertions.html) 包含了几种类型:
162 |
163 | - **Chai**:断言
164 | - `expect('test').to.be.a('string')`:BDD 风格
165 | - `assert.equal(3, 3, 'vals equal')`:TDD 风格
166 | - **Chai jQuery**:关于 DOM 的断言
167 | - `expect(\$el).to.have.attr('foo', 'bar')`
168 | - **Sinon-Chai**:关于函数调用情况的断言
169 | - `expect(spy).to.be.called`
170 | - **`.should()`**:在 Cypress 中封装了以上所有可用断言
171 | - `cy.get('li.selected').should('have.length', 3)`:should
172 | - `cy.get('div').should(($div) => { expect($div)... })`:BDD
173 |
174 | 注意到 [Cypress 使用 Mocha BDD 风格的生命周期](https://docs.cypress.io/guides/references/bundled-tools.html#Mocha),
175 | 不同测试的命名风格:
176 |
177 | | Mocha BDD | Mocha TDD | Jest |
178 | | :------------------- | :-------------- | :---------- |
179 | | `describe`/`context` | `suite` | `describe` |
180 | | `specify`/`it` | `test` | `test`/`it` |
181 | | `before` | `setup` | `beforeAll` |
182 | | `after` | `teardown` | `afterAll` |
183 | | `beforeEach` | `suiteSetup` | `before` |
184 | | `afterEach` | `suiteTeardown` | `after` |
185 |
186 | ### `cy` 命令
187 |
188 | 用来编写测试
189 |
190 | - 测试
191 | - `should`:断言
192 | - `then`:类似 Promise 的 then
193 | - `each`:遍历执行(对于数组)
194 | - `spread`:then 的 each 版
195 | - 查询
196 | - `contains`、`get`
197 | - `children`、`closest`、`find`
198 | - `eq`、`filter`、`not`
199 | - `first`、`last`
200 | - `next`、`nextAll`、`nextUntil`
201 | - `parent`、`parents`、`parentsUntil`
202 | - `prev`、`prevAll`、`prevUntil`
203 | - `siblings`
204 | - `window`、`document`、`title`
205 | - `its`:取得对象中的字段,如 `cy.get('ul li').its('length')`
206 | - `root`:当前上下文的根元素节点
207 | - `within`:设定上下文元素(类似 JS 中的 with)
208 | - 操作
209 | - 用户操作
210 | - `click`、`dblclick`、`rightclick`
211 | - `blur`、`focus`、`focused`
212 | - ~~`hover`~~:不支持
213 | - `trigger`:触发事件
214 | - 表单/输入框
215 | - `check`、`uncheck`、`select`
216 | - `clear`:清除文本框
217 | - `type`:输入文本框
218 | - `submit`
219 | - `scrollIntoView`、`scrollTo`
220 | - `invoke`:调用对象中的函数,如 `cy.get('div').invoke('show')`
221 | - 浏览器
222 | - `viewport`:设置应用窗口大小
223 | - `clearCookie`、`clearCookies`、`getCookie`、`getCookies`、`setCookie`
224 | - `clearLocalStorage`
225 | - 网络请求
226 | - `visit`、`reload`:访问
227 | - `hash`、`location`、`url`:获取
228 | - `go`:历史跳转,相当于 `window.history.go`
229 | - `request`:HTTP 请求
230 | - `server`:启动一个服务
231 | - `route`:跳转路由
232 | - 功能性
233 | - 任务
234 | - `log`、`debug`、`pause`
235 | - `exec`:执行 shell 命令
236 | - `readFile`、`writeFile`
237 | - `screenshot`:截屏到 `/screenshots`
238 | - `fixture`:读取 `/fixtures` 中文件内容
239 | - `task`:执行 `/plugins` 中声明的事件
240 | - 语法糖
241 | - `as`:设置为别名
242 | - `and`:进行多个测试
243 | - `end`:截断当前测试(后续链式调用将重新计算)
244 | - `wrap`:包装一个对象(以便支持 cy 命令)
245 | - 调用监听
246 | - `spy`:监听对象中的函数
247 | - `stub`:替换对象中的函数(用于监听)
248 | - Timer
249 | - `clock`:覆写原生时钟(将会影响 setTimeout 等原生函数)
250 | - `tick`:跳过时间,加快测试速度(需要先 `cy.clock()`)
251 | - `wait`:显式等待(不推荐使用)
252 |
253 | ### `Cypress` API
254 |
255 | 包含定制选项方法,或公共静态方法
256 |
257 | - 定制
258 | - `Commands`:添加自定义命令
259 | - `Cookies`:测试时的 Cookie 行为控制
260 | - `Screenshot`:截屏参数配置
261 | - `SelectorPlayground`:调整选择器规则
262 | - `Server`:调整 `cy.server()` 默认参数
263 | - `config`:修改 Cypress 的 [配置选项](https://docs.cypress.io/guides/references/configuration.html)
264 | - `env`:管理自定义全局变量
265 | - `log`:配置 log 参数
266 | - 辅助
267 | - `dom`:一组 dom 相关方法
268 | - 如 `Cypress.dom.isHidden($el)`
269 | - `isCy`:是否是 cy 对象
270 | - 环境信息
271 | - `arch`:获取 CPU 架构,来源于 Node `os.arch()`
272 | - `browser`:获取浏览器信息
273 | - `platform`:获取操作系统名字
274 | - `spec`:当前测试文件信息
275 | - `version`:版本号
276 |
277 | ### 事件
278 |
279 | 事件绑定机制是 [Node Events](https://nodejs.org/api/events.html),
280 | 用法如:`Cypress.on`/`cy.on`
281 |
282 | - 应用(页面)事件
283 | - `uncaught:exception`
284 | - `window:confirm`、`window:alert`、`window:before:load`、`window:load`、`window:before:unload`、`window:unload`
285 | - `url:changed`
286 | - Cypress 事件
287 | - `fail`
288 | - `viewport:changed`
289 | - `scrolled`
290 | - `command:enqueued`、`command:start`、`command:end`、`command:retry`
291 | - `log:added`、`log:changed`
292 | - `test:before:run`、`test:after:run`
293 |
294 | ## Cypress 典型代码
295 |
296 | 查看上文中的 [实战链接](#%e5%ae%9e%e6%88%98) 及 [典型代码](#%e6%b5%8b%e8%af%95%e6%96%87%e4%bb%b6-%e5%85%b8%e5%9e%8b%e4%bb%a3%e7%a0%81)
297 |
--------------------------------------------------------------------------------
/docs/note/10.frontend/frontend-hardcore-overview/frontend-hardcore-overview.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 硬核前端(劝退篇)
3 | date: 2019-12-14 22:03:19
4 | permalink: /frontend/frontend-hardcore-overview
5 | categories:
6 | - 前端开发
7 | tags:
8 | - 杂谈
9 | ---
10 |
11 | # 硬核前端(劝退篇)
12 |
13 | ## 当个前端工程师
14 |
15 | ### 这算是前端**工程师**吗?
16 |
17 | 你以为前端就是切图写页面吗?
18 |
19 | 你以为互联网行业有高工资,前端又好像门槛相对比较低,
20 | 报了个培训班学了三个月,找到工作拿个十几 K 就喜大普奔吗?
21 |
22 | 你以为写了个仿饿了么、仿网易云、写了个轮播,
23 | 学了下 React/Vue 用法(甚至还读了源码),
24 | 就算前端入门了吗?就了解前端了吗?
25 |
26 | 不不不,这只是最初的阶段。
27 |
28 | 
29 |
30 | #### 那前端还能做些什么
31 |
32 | [这个程序员写的免费在线 PS,让他三十岁前财务自由](https://zhuanlan.zhihu.com/p/70636726)
33 |
34 | [拆解一款 Webgl 渲染器](https://zhuanlan.zhihu.com/p/28108991)
35 |
36 | [从 VSCode 看大型 IDE 技术架构](https://zhuanlan.zhihu.com/p/96041706)
37 |
38 | [页面可视化搭建工具前生今世](https://zhuanlan.zhihu.com/p/37171897)
39 |
40 | #### 前端行业的近况
41 |
42 | > 每 18 至 24 个月,前端都会难一倍。 —— 赫门 / 2015 “深 JS”大会
43 |
44 | [在 2016 年学 JavaScript 是一种什么样的体验?](https://zhuanlan.zhihu.com/p/22782487)
45 |
46 | > 在你学会一项前端技术的时候,另外三项新技术已经发布了。不仅如此,你刚学会的那个也已经被弃用了。
47 | > —— [[译] 为何前端开发如此不稳定](https://juejin.im/post/5b1f2f1ae51d4506894983ae)
48 |
49 | [为什么很多技术都觉得前端很简单?](https://www.zhihu.com/question/353545736/answer/935917542)
50 |
51 | [未来的前端工程师](https://juejin.im/post/5a474c8ff265da430a50ea57)
52 |
53 | [给 2019 前端的 5 个建议](https://github.com/camsong/blog/issues/11)
54 |
55 | [「2019 JSConf.Asia - 尤雨溪」在框架设计中寻求平衡](https://zhuanlan.zhihu.com/p/76622839)
56 |
57 | [现代 Web 开发的现状与未来(JSDC 2019 演讲全文)](https://zhuanlan.zhihu.com/p/88616149)
58 |
59 | [这些年的体验技术部 · 前端工程 - 与云共舞,未来已来](https://www.yuque.com/afx/about/basement)
60 |
61 | [《蚂蚁前端研发最佳实践》文字稿](https://github.com/sorrycc/blog/issues/90)
62 |
63 | [VS Code 成主宰、Vue 备受热捧!2019 前端开发趋势必读](https://zhuanlan.zhihu.com/p/97741102)
64 |
65 | 
66 |
67 | [2019 年 JavaScript 明星项目](https://risingstars.js.org/2019/zh)
68 | [2018 年 JavaScript 明星项目](https://risingstars.js.org/2018/zh)
69 | [The State of JavaScript 2019](https://2019.stateofjs.com/zh/)
70 |
71 | ### 所以,前端工程师是什么?
72 |
73 | > 前端工程师首先是个程序员,其次也是个软件工程师。
74 |
75 | 前端工程师应该掌握扎实的 JS、CS 理论知识和编程功底。
76 | 并将工作尽可能得工程化。
77 |
78 | 虚假的前端工程师:
79 |
80 | 
81 |
82 | 真正的前端工程师:
83 |
84 | 
85 |
86 | #### 如何成为优秀的前端工程师
87 |
88 | 简单的道理:不会就学
89 |
90 | 并且要学习的是精华的、核心的、通用的、本质的部分,
91 | 而不是 API 和用法的表皮。
92 |
93 | > 众所周知,技术会过时。
94 | > 有的工作准入门槛低,但这不等于简单。
95 | > 你应该做的是去学习基本功。比如啥操作系统,算法,编程语言,体系结构这些。
96 | > —— [半衰期](https://zhuanlan.zhihu.com/p/84927997)
97 |
98 | [打破框架的范式之争](https://zhuanlan.zhihu.com/p/82958907)
99 |
100 | > 很多时候,人们排斥一个新技术,并不是因为新技术不好,而是这可能让自己多年精通的老手艺带来的 “竞争优势” 完全消失。可能一个织布老专家手工织布效率是入门学员的 5 倍,但换上织布机器后,这个差异很快会被抹平,老织布专家面临被淘汰的危机,所以维护这份老手艺就是维护他自己的利益。希望每个团队中的老织布工人都能主动引入织布机。
101 | > —— [精读《unstated 与 unstated-next 源码》](https://zhuanlan.zhihu.com/p/93500556)
102 |
103 | ## 小结
104 |
105 | > 生产力决定生产关系:生产力对生产关系起着决定作用、支配作用,其主要表现在两个方面:第一,生产力的性质决定生产关系的性质。第二,生产力的发展变化决定生产关系的改变。
106 | > 生产关系反作用于生产力:这种反作用表现为两种情况:第一,适合生产力的性质和发展要求的先进的生产关系,促进生产力的发展;第二,不适合生产力的性质和发展要求的落后的生产关系,阻碍生产力的发展。
107 | > —— [马克思主义哲学](https://zh.wikipedia.org/wiki/%E5%8E%86%E5%8F%B2%E5%94%AF%E7%89%A9%E4%B8%BB%E4%B9%89)
108 |
109 | > 通常来说,我们都会认为高工资来自于高技能。但从逻辑上来说,这是不对的。因为从经济学角度来说,高工资只能来自于高利润,这是一个很容易理解的收支平衡问题。
110 | > 而 IT 行业之所以能拥有高利润,是因为过去的这些年,IT 行业确实极大的促进了生产力的发展。所以,才会有高利润溢价推高程序员的工资。
111 | > —— [非程序员说编程有什么难的,作为程序员,该怎么回答这个问题? - 沈世钧](https://www.zhihu.com/question/356294204/answer/935303946)
112 |
113 | 如果看完本文中的链接,你的感受是:
114 |
115 | > 卧槽!这都什么东西?球球你们别学了,我跟不上了。
116 |
117 | 那么你**可能**不太适合这个行业,
118 | 建议赶紧转行,找一份真正适合自己的工作,
119 | 而不是强行进入这个行业,当个切图仔调包侠。
120 | 然后过两三年才发现自己不适合这个工种,
121 | 并且由于高深的技术又不会、搬砖又拼不过年轻人,只能被裁员这样子。
122 | ( 战 术 劝 退 )
123 |
124 | 
125 |
126 | 如果你的感受是:
127 |
128 | > 卧槽!爽文!搞技术太酷了!打开了新世界!我来!
129 |
130 | 那么恭喜,说明你有一定的技术储备和技术思维,
131 | 并且拥有相当的技术热情,你**可能**非常有机会!
132 | 欢迎你!期待你能创造更多价值!
133 |
--------------------------------------------------------------------------------
/docs/note/10.frontend/frontend-hardcore-overview/img/dk-effect.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seognil/fe-foundation/74290e0ec2a3f0d8cea2c719c6e1dd21a3c2fbb0/docs/note/10.frontend/frontend-hardcore-overview/img/dk-effect.jpg
--------------------------------------------------------------------------------
/docs/note/10.frontend/frontend-hardcore-overview/img/fe-hardcore-fs8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seognil/fe-foundation/74290e0ec2a3f0d8cea2c719c6e1dd21a3c2fbb0/docs/note/10.frontend/frontend-hardcore-overview/img/fe-hardcore-fs8.png
--------------------------------------------------------------------------------
/docs/note/10.frontend/frontend-hardcore-overview/img/fe-naive-fs8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seognil/fe-foundation/74290e0ec2a3f0d8cea2c719c6e1dd21a3c2fbb0/docs/note/10.frontend/frontend-hardcore-overview/img/fe-naive-fs8.png
--------------------------------------------------------------------------------
/docs/note/10.frontend/frontend-hardcore-overview/img/go-home.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seognil/fe-foundation/74290e0ec2a3f0d8cea2c719c6e1dd21a3c2fbb0/docs/note/10.frontend/frontend-hardcore-overview/img/go-home.jpeg
--------------------------------------------------------------------------------
/docs/note/10.frontend/frontend-hardcore-overview/img/stateofjs2019-dark-fs8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seognil/fe-foundation/74290e0ec2a3f0d8cea2c719c6e1dd21a3c2fbb0/docs/note/10.frontend/frontend-hardcore-overview/img/stateofjs2019-dark-fs8.png
--------------------------------------------------------------------------------
/docs/note/10.frontend/frontend-hardcore-overview/img/stateofjs2019tshirt-illustration.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seognil/fe-foundation/74290e0ec2a3f0d8cea2c719c6e1dd21a3c2fbb0/docs/note/10.frontend/frontend-hardcore-overview/img/stateofjs2019tshirt-illustration.png
--------------------------------------------------------------------------------
/docs/note/20.computer-science/map-of-computer-science-fs8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seognil/fe-foundation/74290e0ec2a3f0d8cea2c719c6e1dd21a3c2fbb0/docs/note/20.computer-science/map-of-computer-science-fs8.png
--------------------------------------------------------------------------------
/docs/note/21.tool-skills/01.git/img/git-cheatsheet-cn.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seognil/fe-foundation/74290e0ec2a3f0d8cea2c719c6e1dd21a3c2fbb0/docs/note/21.tool-skills/01.git/img/git-cheatsheet-cn.jpeg
--------------------------------------------------------------------------------
/docs/note/21.tool-skills/01.git/img/git-flow-fs8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seognil/fe-foundation/74290e0ec2a3f0d8cea2c719c6e1dd21a3c2fbb0/docs/note/21.tool-skills/01.git/img/git-flow-fs8.png
--------------------------------------------------------------------------------
/docs/note/21.tool-skills/01.git/img/git-mindmap-fs8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seognil/fe-foundation/74290e0ec2a3f0d8cea2c719c6e1dd21a3c2fbb0/docs/note/21.tool-skills/01.git/img/git-mindmap-fs8.png
--------------------------------------------------------------------------------
/docs/note/21.tool-skills/02.markdown.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Markdown 学习指南
3 | date: 2019-12-26 12:27:58
4 | permalink: /cs/markdown
5 | categories:
6 | - 计算机科学
7 | tags:
8 | - 工具
9 | - markdown
10 | ---
11 |
12 | # Markdown 学习指南
13 |
14 | ## Markdown 简介
15 |
16 | ### 什么是 Markdown
17 |
18 | > Markdown 是一种轻量级标记语言。它允许人们“使用易读易写的纯文本格式编写文档,然后转换成有效的 XHTML(或者 HTML)文档”。
19 | > 当前许多网站都广泛使用 Markdown 来撰写帮助文档或是用于论坛上发表消息。例如:GitHub、reddit、Diaspora、Stack Exchange、OpenStreetMap 、SourceForge 等。甚至 Markdown 能被使用来撰写电子书。
20 |
21 | 文件后缀常用 `.md` 或 `.markdown`,
22 | Markdown 的配套工具有语法高亮、解析工具等…
23 |
24 | GitHub 大多数项目中的 `README.md` 就是用 Markdown 写的项目说明,
25 | 本站的所有文章也都是用 Markdown 写的。
26 |
27 | 当 Markdown 自身规则无法满足时,**也可以**写任意合法的 **HTML** 代码。
28 |
29 | ### 什么是 TOC
30 |
31 | Table Of Contents 的缩写,表示目录。
32 |
33 | 由于 Markdown 的规则具有约束性,
34 | 能够很方便地根据 Markdown 内容生成目录,
35 | 有很多工具可以自动化地做这个事情。
36 |
37 | ### 为什么要学习使用 Markdown
38 |
39 | - 写起来简便
40 | - 写 GitHub 的 `README`
41 | - 为了看懂别人的内容
42 |
43 | ## 学习 Markdown
44 |
45 | ### 概览
46 |
47 | - 耗时:几分钟
48 | - 难点:无
49 | - 工具:一大堆
50 |
51 | ### 学习路线
52 |
53 | - 前置学习
54 | - HTML
55 | - 学习 Markdown
56 | - Markdown 全部基本语法
57 | - 了解:不同工具可能会有自己的扩展语法
58 | - 实战
59 | - 写写学习笔记
60 | - 给自己的项目写 Readme
61 |
62 | ## 资料
63 |
64 | ### 自学教材
65 |
66 | - [Mastering Markdown](https://guides.github.com/features/mastering-markdown/)
67 | - [Markdown Cheatsheet](https://github.com/tchapi/markdown-cheatsheet)
68 | - [Markdown - Learn X in Y minutes](https://learnxinyminutes.com/docs/markdown/)
69 |
70 | ### 写作软件(桌面)
71 |
72 | 我个人不用其他的写作软件…
73 | 在 [学习方法论](/study/crash-course-study-skills) 一文中,我提到我使用 “云盘 + VS Code” 的知识管理模式
74 |
75 | 对于 Markdown 写作,我自己主要是:
76 |
77 | - [VS Code](https://code.visualstudio.com/)
78 | - Markdown 插件:[Markdown All in One](https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one)
79 | - 语法高亮:[Dracula](https://draculatheme.com/)
80 | - 格式化:[Prettier](https://prettier.io/)
81 | - 编译发布:[VuePress](https://vuepress.vuejs.org/zh/)
82 |
83 | Markdown 的某些特性可能有多种写法,
84 | 使用格式化工具可以保持编码风格统一。
85 |
86 | 而现成的编译器可能会集成代码块语法高亮等功能。
87 |
88 | ### 写作软件(在线)
89 |
90 | - [马克飞象](https://maxiang.io/)
91 | - [DILLINGER](https://dillinger.io/)
92 |
93 | ### Markdown JS 解析器
94 |
95 | - [markdown-it](https://github.com/markdown-it/markdown-it)
96 | - [marked](https://github.com/markedjs/marked)
97 | - [markdown-js](https://github.com/evilstreak/markdown-js)
98 |
99 | ### 工具
100 |
101 | - [markdown-here](https://github.com/adam-p/markdown-here)
102 | - [doctoc](https://github.com/thlorenz/doctoc)
103 | - [github-markdown-toc](https://github.com/ekalinin/github-markdown-toc)
104 |
105 | ## Markdown 典型代码
106 |
107 | ```markdown
108 |
109 |
110 | # H1
111 |
112 | ## H2
113 |
114 | ###### H6
115 |
116 |
117 |
118 | **粗体 strong**
119 | _斜体 em_
120 | ~~删除线 s~~
121 |
122 | 注意:以上标记如果边界处有空格,根据工具不同可能会造成解析失败
123 | 例如: _ 可能无效 _
124 |
125 |
126 |
127 | 像这样用反引号包起来 → `exit vim`
128 | 使用场景:JavaScript 中有 `var` 关键字。
129 |
130 |
131 |
132 | 也可以使用任意合法 HTML 标签
133 |
134 | ```
135 |
136 | ```markdown
137 |
138 |
139 | > 以右尖括号开头的段落表示引用
140 | > 支持很多其他 **Markdown 语法**
141 | >
包括换行
142 | >
143 | > > 也可以嵌套
144 | > > 本质上是转义成 blockquote 标签
145 |
146 |
147 |
148 | 一行的最后接两个空格(选中看看) →
149 | 再写另一行,则会形成换行。
150 |
151 | GitHub 好像不加空格也可以自动视为换行
152 | Vuepress 使用的编译器则不行,必须加上空格
153 |
154 | 或者显式地
155 |
156 |
157 |
158 | ---
159 |
160 | ---
161 |
162 | ---
163 |
164 | 这些字符,连续三个以上
165 |
166 | 或者显式地
167 | ```
168 |
169 | ```markdown
170 |
171 |
172 | [链接文字](https://rualc.me/)
173 |
174 | 编译成:
175 | 链接文字
176 |
177 | 同名链接的写法 ↓
178 |
179 | 等价于:
180 | [https://rualc.me/](https://rualc.me/)
181 |
182 | VuePress 不支持裸链接直接编译,可以使用同名链接的写法
183 | GitHub 则是直接支持编译
184 |
185 | ---
186 |
187 | [链接也可以分开写][home]
188 |
189 | [home]: https://rualc.me/ '这里可以写注释'
190 |
191 |
192 |
193 | 
194 |
195 | 编译成:
196 |
197 | ```
198 |
199 | ```markdown
200 |
201 |
202 | - 列表项
203 | - 子项
204 | - 子项
205 | - 属于同一个列表
206 | - 也可以用不同的标记
207 | - 但是需要保持一致(这里是演示)
208 | - 使用格式化工具比较好
209 |
210 | * 不同的一级标记则视为另一个列表
211 | - 子项
212 |
213 |
214 |
215 | 1. 有序列表
216 | 2. 有些工具会自动补齐下一行的数字
217 | 3. 但其实数字值其实无所谓(解析工具自动判断)
218 |
219 | 4. 另起一行不会视为另一个列表(因为自动解析规则)
220 | 5. 请插入
来实现
221 |
222 |
223 |
224 | 1. 像这样才是另一个列表
225 |
226 |
227 |
228 | - [ ] 未完成 `[ ]` 表示未完成
229 | - [ ] 未完成 实际上会编译成
230 | - [x] 已完成 `[x]` 表示已完成
231 | - [ ] 默认可能无法直接编辑(通过 `disabled` 属性实现)
232 | - [x] GitHub 的 issue 页支持直接编辑(并保存)
233 |
234 |
235 |
236 | | 表格 | 第二栏 | 第三栏 | |
237 | | -------- | :------- | -------: | :----: |
238 | | 表格内容 | 左对齐 ↑ | 右对齐 ↑ | 居中 ↑ |
239 | | | 文字 | 文字 | 文字 |
240 |
241 | 建议编写时使用等宽字体
242 | Prettier 格式化可以自动对齐每一栏
243 | ```
244 |
245 | `````markdown
246 |
247 |
248 | ```javascript
249 | var a = 2;
250 | ```
251 |
252 |
253 |
254 | ````markdown
255 | ```
256 | 三个 ` 表示代码块 后面可以指定语言(也可以不)
257 | ```
258 |
259 | 代码块可以像这样嵌套 ↑,
260 | 写法上类似 #,只要多写几个反引号,则内部不会转义
261 |
262 | 其实这个版块整个都被包裹在代码块里
263 | 所以你看到的 Markdown 代码都没有被转义
264 |
265 | 可以到这里看看本文的 Markdown 源码是怎么写的:
266 | https://raw.githubusercontent.com/seognil/fe-foundation/master/docs/cs/markdown.md
267 | ````
268 | `````
269 |
--------------------------------------------------------------------------------
/docs/note/21.tool-skills/31.introduction-to-terminal.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 命令行 简介
3 | date: 2019-11-09 18:25:16
4 | permalink: /workspace/introduction-to-terminal
5 | categories:
6 | - 开发环境
7 | tags:
8 | - 命令行
9 | - mac
10 | ---
11 |
12 | # 命令行 简介
13 |
14 | ## 什么是 命令行
15 |
16 | > 命令行界面(英语:Command-Line Interface,缩写:CLI)是在图形用户界面得到普及之前使用最为广泛的用户界面,它通常不支持鼠标,用户通过键盘输入指令,计算机接收到指令后,予以执行。也有人称之为字符用户界面(character user interface, CUI)。
17 |
18 | - [Computers 101: terminals, kernels and shells](https://www.integralist.co.uk/posts/terminal-shell/)
19 | - [终端、Shell、tty 和控制台(console)有什么区别?](https://www.zhihu.com/question/21711307)
20 | - [什麼是程序 (Process) - 鳥哥的 Linux 私房菜](http://linux.vbird.org/linux_basic/0440processcontrol.php)
21 |
22 | ## 打开和使用 命令行
23 |
24 | 打开系统自带的终端,然后使用命令行界面:
25 |
26 | - Mac(Terminal)
27 | - 按 Cmd+Space 打开 `Spotlight Search` 或 `聚焦搜索`
28 | - 键入 `terminal` 或 `终端`
29 | - 选择 `Terminal.app` 或 `终端` 启动
30 | - Windows(CMD 或 PowerShell)
31 | - 按 Win 键(或鼠标点击屏幕左下角的徽标),打开 Windows 菜单
32 | - 键入 `cmd` 或 `powershell`
33 | - 选择 `CMD` 或 `命令提示符` 或 `Windows PowerShell` 启动
34 |
35 | 将会启动一个黑色的窗口,然后:
36 |
37 | - 键入 `ls` 或 `dir` 并回车
38 |
39 | 这个命令将会在终端中,打印显示当前文件夹下的所有文件。
40 | 这样就完成了一个基本的命令行操作。
41 |
42 | 这是我的终端界面 ↓(参考下一篇文章 [打造趁手的终端](/workspace/terminal-settings))
43 |
44 | 
45 |
46 | ## 为什么要使用 命令行
47 |
48 | - 很多优秀工具 _只有_ 或 _优先_ 提供命令行的版本(如 Node.js、Brew)
49 | - 命令行很方便
50 | - 相比定位鼠标,敲键盘可以直接通过肌肉记忆完成,鲁棒性高
51 | - 常用工作流可以封装成代码脚本,一组快捷键或几个字符就能轻松执行
52 | - 降低资源消耗(如远程登录)
53 |
54 | ## 命令行 相关
55 |
56 | ### 命令行 中的退出/中断
57 |
58 | 有一个著名的问题:
59 | [How To Exit Vim? Multiple Ways To Quit Vim Editor](https://itsfoss.com/how-to-exit-vim/)
60 |
61 | VI 或 VIM 是一个 Linux 上流行的命令行编辑器,
62 | 常用于远程登录时的文件编辑。
63 |
64 | 它的退出命令是通过键入 `:q` 并回车
65 |
66 | 其他不同工具的退出方式可能是以下几种之一:
67 | Ctrl+C、Ctrl+D、Q、
68 | `exit`、`quit`、`exit()`
69 |
70 | ### 命令的帮助文档
71 |
72 | 一般来说,不可能记住所有命令的所有用法,
73 | 这时候,懂的如何查询文档就非常重要。
74 |
75 | 在命令行中,有以下几种查询方式:
76 |
77 | - 命令**内置**的 `help` 子命令,
78 | 用法例如: `git help`、`git --help`、`git add --help`
79 | - `man`:Unix 系统和 PowerShell **自带**的命令,
80 | 用法例如:`man ls`
81 | - `tldr`:一个需要 [安装](https://github.com/tldr-pages/tldr) 的工具,能够显示其他命令的**常见用法**,
82 | 用法例如:`tldr ls`、`tldr git`、`tldr git add`
83 |
84 | * [explainshell](https://explainshell.com/):一个在线解释网站,能够解释你输入的命令和参数
85 |
86 | ### 管道
87 |
88 | Unix 中有管道的概念,用于拼接不同命令,
89 | 将上一个命令的输出当做下一个命令的输入,
90 | 实现命令的组合运用。
91 |
92 | 命令的拼接有两种主要方式:
93 |
94 | [管道 (Unix)]()
95 | 下面 `ls` 和 `tail` 是两个独立的命令,`|` 是管道
96 |
97 | ```bash
98 | ls -l | tail -n 2
99 | ```
100 |
101 | [xargs](https://zh.wikipedia.org/wiki/Xargs)
102 | 下面 `where` 和 `ls` 是两个命令,`xargs` 用于传递参数
103 |
104 | ```bash
105 | where bash | xargs ls -la
106 | ```
107 |
108 | ### 环境变量
109 |
110 | 使用 terminal 时,每个新窗口都将基于系统环境变量和启动配置建立一个独立的会话,
111 | 所谓环境变量,也就是 `PATH`,
112 | 所谓启动配置,也就是 `~/.bashrc`、`~/.zshrc` 等配置文件,
113 |
114 | 任何未固化的数据和设定都将在窗口关闭后丢失,
115 | 所以需要根据需求自己调整配置文件。
116 | (参考后文中的提到的 `dotfile`)
117 |
118 | 有一个名为 `tmux` 的命令行工具,可以在一个窗口内显示和管理多个窗口(session)
119 |
120 | ### 术语解释
121 |
122 | - **Terminal**:终端,曾经指一类计算机硬件,现在泛指 Terminal emulator,也就是虚拟终端(一类软件)
123 | - **shell**:壳层,前接 Terminal、后接 Kernel 的一层接口,指终端软件启动后窗口中的看到的内容
124 |
125 | * **CLI**:Command-line interface,命令行界面
126 | * **GUI**:Graphical user interface,图形用户界面
127 | * **Unix-like**:泛指所有具有类似 Unix 表现和行为的系统。
128 |
129 | - **Kernel**:内核,系统底层代码
130 | - **console**:控制台,曾经指一类计算机硬件,现在泛指调试面板(如浏览器的)
131 | - **tty**:来源于 Teletypewriter 的缩写,指上世纪计算机硬件终端的打字机部分,现在泛指虚拟终端的输入界面
132 | - **session**:会话,指一组执行命令的环境,由虚拟终端提供。
133 | 创建多个会话(表现为多窗口或切换)可以并行处理不同任务。
134 | - **PATH**:环境变量,系统提供的配置入口,用于检索可执行文件
135 |
136 | * **dotfile**:泛指以 `'.'` 开头的文本文件,在 Unix-like 系统中是隐藏文件,
137 | 一般用作程序配置,例如:`.bashrc`,复制粘贴该文件即可直接同步配置
138 | - 一个高赞配置 [Mathias’s dotfiles](https://github.com/mathiasbynens/dotfiles)
139 | - 我的 [基本环境自动配置脚本(未完成)](https://github.com/seognil/dotfiles)
140 | * **rc**:常用于 dotfile 文件名的结尾,表示这是配置文件
141 | (rc 可解释为 runcom、run commands、runtime configuration 等)
142 | 如:`.bashrc、.zshrc、.npmrc`
143 |
144 | - **ping**:命令行中检查地址可访问性的工具,例如 `ping rualc.me`
145 | - **curl**:是 Client URL 的缩写,命令行中的地址访问工具,例如 `curl -L rualc.me`
146 |
147 | ### 不同的 shell
148 |
149 | 不同的 shell,语法有一些差别。
150 | 在选择自己的主力 shell 时,根据自己的喜好,以及需要注意兼容性。
151 |
152 | - [Introduction to if - Bash](http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.html)
153 | - [Conditionals (If, Else, Switch) - Fish](https://fishshell.com/docs/current/tutorial.html#tut_conditionals)
154 |
155 | ```bash
156 | # bash
157 | function comp {
158 | local value=$1
159 | if [ $value -gt 100 ]; then
160 | echo "'$value' is in (100, Inf)"
161 | elif [ $value -gt 50 ]; then
162 | echo "'$value' is in (50, 100]"
163 | else
164 | echo "'$value' is in (-Inf, 50)"
165 | fi
166 | }
167 |
168 | # fish
169 | function comp
170 | set -l value $argv[0]
171 | if [ $value -gt 100 ]
172 | echo "'$value' is in (100, Inf)"
173 | else if [ $value -gt 50 ]
174 | echo "'$value' is in (50, 100]"
175 | else
176 | echo "'$value' is in (-Inf, 50)"
177 | end
178 | end
179 | ```
180 |
181 | ### proxy 和 registry
182 |
183 | 对于网路,理解相关概念能够更好地运用它
184 |
185 | #### proxy
186 |
187 | proxy 是指“代理”,作用可能是以下之一
188 |
189 | - 授权访问(防火墙)
190 | - 加密通讯(安全性)
191 | - 节约网络流量(内网)
192 | - 网络质量优化(稳定性)
193 |
194 | #### registry
195 |
196 | 在命令行中下载工具,实际上是从某个地址传输数据。
197 | (如 `github.com`、`npmjs.org`)
198 |
199 | 根据自己的网络环境,进行“换源”操作,或许可以提高下载速度,
200 | 如调整 `brew remote`、`npm registry` 等。
201 |
--------------------------------------------------------------------------------
/docs/note/21.tool-skills/32.terminal-settings.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 打造趁手的终端
3 | date: 2019-11-09 18:25:16
4 | permalink: /workspace/terminal-settings
5 | categories:
6 | - 开发环境
7 | tags:
8 | - 命令行
9 | - mac
10 | - zsh
11 | - brew
12 | ---
13 |
14 | # 打造趁手的终端
15 |
16 | ## 代理(proxy)
17 |
18 | 在上一篇文章 [命令行简介](/workspace/introduction-to-terminal) 中,我们提到代理有诸多好处,正确配置或能直接提高生产效率。给浏览器、软件、Terminal 或是其他工具配置代理,不同工具的配置方式可能不同。
19 |
20 | 对于 Terminal 来说是通过命令来配置(参考 [Set HTTP(s) Proxy in Windows Command Line / MAC Terminal](https://itectec.com/set-https-proxy-in-windows-command-line-environment/) 这篇文章):
21 |
22 | ```shell
23 | # 其中的 http://127.0.0.1:1080 改成自己的代理地址
24 |
25 | # mac
26 | export ALL_PROXY='http://127.0.0.1:1080'
27 |
28 | # windows
29 | set http_proxy='http://127.0.0.1:1080'
30 | set https_proxy='http://127.0.0.1:1080'
31 | ```
32 |
33 | 可以根据需要到自己的 shell 配置文件(如 `~/.bashrc`、`~/.zshrc`)中,封装成函数,以便更方便地控制启用。
34 |
35 | ```bash
36 | # ~/.zshrc
37 | function proxyon() {
38 | export ALL_PROXY='http://127.0.0.1:1080'
39 | }
40 |
41 | function proxyoff() {
42 | unset ALL_PROXY
43 | }
44 |
45 | # (启动 shell 时)直接运行 proxyon,启用代理
46 | proxyon
47 | ```
48 |
49 | 测试代理的连通性,可以在 terminal 中尝试用 `curl` 命令访问网站:
50 |
51 | ```shell
52 | curl google.com
53 | # curl zhihu.com
54 | # curl baidu.com
55 | ```
56 |
57 | 如果能成功返回 HTML 结果,而不是无响应或错误信息,即说明配置有效:
58 |
59 |
60 | ```html
61 |
62 | 301 Moved
63 | 301 Moved
64 | The document has moved
65 | here.
66 |
67 | ```
68 |
69 | ## Homebrew
70 |
71 | > 从命令行中安装工具和软件
72 |
73 | MacOS 生态有中有一个名为 [Homebrew](https://brew.sh/) 的命令行工具(需要额外安装)
74 |
75 | 它类似 Linux 中的 `apt` 或 `yum`,Windows 中的 [Chocolatey](https://chocolatey.org/)。
76 | 或类似 Node.js 的 `npm`、Python 的 `pip`、PHP 的 `composer` …
77 |
78 | 虽然上述各种工具是不同生态中的不同工具,但它们有一个共同点:通过命令行安装其他程序。不需要再通过浏览器手动点击下载,软件环境的配置过程能够更方便和高效。
79 |
80 | ### 安装 Homebrew
81 |
82 | (可以先调整好代理,这样 brew 的下载速度可能会更快。)
83 |
84 | [安装 Homebrew](https://brew.sh/):
85 |
86 | ```shell
87 | /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
88 | ```
89 |
90 | 安装完成后在命令行中键入命令 `brew`,将会打印 brew 自带的帮助文档:
91 |
92 | ```shell
93 | Example usage:
94 | brew search TEXT|/REGEX/
95 | brew info [FORMULA|CASK...]
96 | brew install FORMULA|CASK...
97 | brew update
98 | brew upgrade [FORMULA|CASK...]
99 | brew uninstall FORMULA|CASK...
100 | brew list [FORMULA|CASK...]
101 |
102 | Troubleshooting:
103 | brew config
104 | brew doctor
105 | brew install --verbose --debug FORMULA|CASK
106 |
107 | Contributing:
108 | brew create URL [--no-fetch]
109 | brew edit [FORMULA|CASK...]
110 |
111 | Further help:
112 | brew commands
113 | brew help [COMMAND]
114 | man brew
115 | https://docs.brew.sh
116 | ```
117 |
118 | 然后我们尝试使用,例如 node 的安装卸载:
119 |
120 | ```shell
121 | brew install node
122 | brew uninstall node
123 | brew upgrade node
124 | brew info node
125 | ```
126 |
127 | brew 整合了 formula(针对命令行工具如 `node`) 和 cask(针对 GUI 软件如 `visual-studio-code`)。
128 |
129 | ```shell
130 | brew install node
131 | brew install visual-studio-code
132 | brew list
133 | brew list --formula
134 | brew list --cask
135 | ```
136 |
137 | #### (可选)安装 brew-cask-upgrade
138 |
139 | [brew-cask-upgrade](https://github.com/buo/homebrew-cask-upgrade) 是 `brew upgrade --cask` 的社区增强版工具。cask 默认的升级策略是跳过那些本身自带更新功能的软件,而 cu 的管理更细致。
140 |
141 | #### 小贴士:软件仓库
142 |
143 | 上述提到的管理工具本身都是下载管理工具,它们不保存第三方软件的安装包,而只是维护下载地址。如果某软件的下载地址不在维护列表内,无法检索到也就无法安装了。
144 |
145 | 这时候就需要设置额外的地址进行下载安装。
146 | (一般会借助 `sh`、`wget`、`curl` 等命令进行下载和安装)
147 |
148 | 例如在 Ubuntu 中安装 Node.js:
149 |
150 | ```shell
151 | sudo apt-get install -y nodejs
152 | ```
153 |
154 | 默认的 apt 源并不维护最新的 Node.js 版本,所以如果需要安装较新的 _Node.js 16_,就需要进行额外配置(参考 [Installation instructions - NodeSource](https://github.com/nodesource/distributions/blob/master/README.md#debinstall) 这篇文章):
155 |
156 | ```shell
157 | curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash -
158 | sudo apt-get install -y nodejs
159 | ```
160 |
161 | ## 打造趁手的终端 {#zsh}
162 |
163 | 个人使用的命令行基本作业环境是:`iTerm2 + zsh + oh-my-zsh`,来代替 MacOS 自带的 `Terminal.app + bash` 方案。
164 |
165 | (另一个流行的配置集是:[Spaceship ZSH](https://github.com/denysdovhan/spaceship-prompt))
166 |
167 | - [iTerm2](https://iterm2.com/):一个 terminal
168 | - `brew install iterm2`
169 | - [zsh](https://github.com/ohmyzsh/ohmyzsh/wiki/Installing-ZSH#how-to-install-zsh-on-many-platforms):一个 shell
170 | - `brew install zsh`
171 | - (安装完后会自动生成启动配置文件 `~/.zshrc`,可以在这个文件中进行深入定制)
172 | - [Oh My Zsh](https://github.com/ohmyzsh/ohmyzsh#getting-started):一个流行的 zsh 配置集
173 | - `sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"`
174 | - [zsh-syntax-highlighting](https://github.com/zsh-users/zsh-syntax-highlighting/blob/master/INSTALL.md#oh-my-zsh):命令语法高亮插件
175 | - (这个是较新的版本,brew 源较旧)`git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting`
176 | - 修改 `~/.zshrc` 文件 `plugins=([...] zsh-syntax-highlighting)`
177 | - [zsh-autosuggestions](https://github.com/zsh-users/zsh-autosuggestions/blob/master/INSTALL.md#oh-my-zsh):根据 history 的自动补全插件
178 | - (这个是较新的版本,brew 源较旧)`git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions`
179 | - 修改 `~/.zshrc` 文件 `plugins=([...] zsh-autosuggestions)`
180 |
181 | 接着可以参考我的另一篇文章 [Mac 和软件](/workspace/mac),安装一些其他的工具。
182 |
183 | 
184 |
--------------------------------------------------------------------------------
/docs/note/21.tool-skills/iterm2-showcase.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/seognil/fe-foundation/74290e0ec2a3f0d8cea2c719c6e1dd21a3c2fbb0/docs/note/21.tool-skills/iterm2-showcase.png
--------------------------------------------------------------------------------
/docs/note/99.about/about-me.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 关于我(2019)
3 | date: 2020-01-13 21:16:36
4 | permalink: /about/me
5 | categories:
6 | - 关于
7 | tags:
8 | - 关于我
9 | ---
10 |
11 | # 关于我(2019)
12 |
13 | ## 我自己
14 |
15 | 目前状态
16 |
17 | - 技能
18 | - 略懂点 JS
19 | - 写过些功能、优化和修复
20 | - 做过点架构改进:
21 | 公司 40 万行 JS 的老项目
22 | 从 ES5/jQuery/Backbone/Underscore/Require.js
23 | 到 TS/React Hooks/Redux/RxJS/Ramda/Webpack
24 | - 学习中
25 | - 修炼 TS
26 | - 学习现代化、工程化前端开发
27 | - 学习 CS
28 | - 其他
29 | - 写文章
30 | - 做了些技术文档翻译
31 |
32 | ## 价值产出
33 |
34 | 给 2019 年(工作以外的部分)做个小结吧
35 |
36 | ### 写文章
37 |
38 | > repo:[seognil/fe-foundation](https://github.com/seognil/fe-foundation)
39 |
40 | (从 2019/10 起)开始系统地写文章,目前有几个系列:
41 |
42 | - [前端入门指南系列](/note/frontend-development-cookbook)
43 | - [JavaScript 语言学习系列](/frontend/javascript-foundation)
44 | - [其他学习指南系列](/study/crash-course-study-skills)
45 |
46 | 主要的目的有两个:
47 |
48 | - 梳理自己的知识体系
49 | - 教朋友学前端
50 |
51 | 然而目前完成度可能只达到的 30%
52 | 还有很多篇没写、或者写了草稿没整理的
53 | ~~毕竟写得比朋友们学得快就好了(~~
54 |
55 | 正式发布的文章:
56 | `cloc` 统计约 五千行
57 | `wc -m` 统计约 17 万字(符)
58 |
59 | 争取明年先完整写完(然后进入日常更新模式)
60 |
61 | ### 开源贡献
62 |
63 | > repo 分类:[seognil-contributor](https://github.com/seognil-contributor)
64 |
65 | #### 翻译和校对
66 |
67 | 完成的工作:
68 |
69 | - [2019 年 JavaScript 明星项目](https://risingstars.js.org/2019/zh):[翻译](https://github.com/bestofjs/javascript-risingstars/pull/49)
70 | - [2018 年 JavaScript 明星项目](https://risingstars.js.org/2018/zh):[翻译](https://github.com/bestofjs/javascript-risingstars/pull/39)
71 | - [The State of JavaScript 2019](https://2019.stateofjs.com/zh/):[翻译](https://github.com/StateOfJS/State-of-JS-2019/pull/50)
72 | - [约定式提交](https://www.conventionalcommits.org/zh-hans/v1.0.0-beta.4/):[校对](https://github.com/conventional-commits/conventionalcommits.org/pull/124)、[改进](https://github.com/conventional-commits/conventionalcommits.org/pull/126)、[版本更新](https://github.com/conventional-commits/conventionalcommits.org/pull/155)
73 | - [Typescript-Handbook](https://github.com/zhongsp/TypeScript):[翻译](https://github.com/zhongsp/TypeScript/pull/274)了 [TS 官方文档中的一章](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html)
74 | - [用 TypeScript 写 React & Redux - 完全指南](https://github.com/seognil-contributor/react-redux-typescript-guide):[翻译](https://github.com/piotrwitek/react-redux-typescript-guide/pull/199)(但还未合并)
75 | - [开始 – React 官方文档](https://zh-hans.reactjs.org/docs/getting-started.html):React 官方翻译计划几篇文章 [翻译和校对](https://github.com/reactjs/zh-hans.reactjs.org/pulls?q=is%3Apr+is%3Aclosed+author%3Aseognil)
76 |
77 | 原本目的有几个:
78 |
79 | - 了解 GitHub 社区(和开源项目协作流程)
80 | - 锻炼英语
81 | - 了解前端和相关生态的知识
82 | - (回馈社区)
83 |
84 | 但是做翻译实在太累了:
85 | 包括翻译和校对、理解和斟酌,尽力追求翻译质量。
86 | 导致我的产出速度大致是每小时一千(汉)字,太花时间了。
87 | 这么看收益还低:
88 | 仅对于学习来说,自己直接看英文版好像更有效率,
89 | 大致理解核心意思就行了,毕竟不用考虑分享就不用锱铢必较。
90 |
91 | (而且已经开始看硬核技术资料的人,英语水平应该也不会差,谁会去看汉化版呢…)
92 |
93 | 所以明年不准备搞了,多搞点代码层面的事情好像更有价值一点……
94 |
95 |
96 |
97 | #### PR
98 |
99 | 做了一些微小的工作:
100 |
101 | - [给 AlloyFinger 修了一个 bug](https://github.com/AlloyTeam/AlloyFinger/pull/85)
102 | - [给 Homebrew cask 提了一个软件升级](https://github.com/Homebrew/homebrew-cask/pull/71677)
103 |
104 | 像上面说的,今年争取多搞点代码的事情。
105 |
106 | ### 造轮子
107 |
108 | > repo 分类:[seognil-lab](https://github.com/seognil-lab)
109 |
110 | 写了点业务中碰到的需求,放在 GitHub 和 npm 上。
111 | 都是些杂七杂八的小玩意儿,后来也没怎么维护和推广,所以基本没产生什么社区影响…
112 | (但是对于工程化的开发模式,基本算是入门并在内部推广了,还算有点收获)
113 |
114 | 部分轮子:
115 |
116 | - [webpack-starter](https://github.com/seognil-lab/webpack-starter)
117 | 已经落地。
118 | 全特性 Webpack 项目模板,作为内部项目技术升级的试验地。
119 | 但还有优化空间(比如热重载没完成)
120 |
121 | - [drag-resize-rotate](https://github.com/seognil-lab/drag-resize-rotate)
122 | 已经落地。
123 | 原本是给常见的 [DRR](https://www.npmjs.com/search?q=drag%20rotate) 功能设计的计算层,
124 | 这样就能方便地支持不同的 UI 层了(比如 jQuery/React/Vue)。
125 | 代码设计上还有优化空间。
126 |
127 | - [vector-math-fp](https://github.com/seognil-lab/vector-math-fp)
128 | 已经落地。
129 | 函数式风格的 2D 平面计算库,
130 | 用于几个内部功能,包括上一个提到的 [DRR](https://github.com/seognil-lab/drag-resize-rotate/blob/master/package.json#L66)。
131 |
132 | - [approx-fix](https://github.com/seognil-lab/approx-fix)
133 | 给 vector-math-fp 用的,
134 | 解决 IEEE 754 问题的快速方案。
135 |
--------------------------------------------------------------------------------
/docs/note/99.about/about-the-guild.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 关于学习指南系列
3 | date: 2019-11-23 23:38:58
4 | permalink: /about/the-guild
5 | categories:
6 | - 关于
7 | tags:
8 | -
9 | ---
10 |
11 | # 关于学习指南系列
12 |
13 | ## TLDR
14 |
15 | 问:和网上其他的学习教程有什么**区别**?
16 |
17 | 答:这**不是教程**或文档,不包括详尽的知识细节和工具使用方法,
18 | 这**只是指南**,记录了我的学习路径,以及关键知识体系笔记。
19 | 其中包含了其他更详细的教程和技术文章的链接,
20 | 如果没有其他的那些优秀材料,我的指南也就毛将焉附。
21 |
22 | 指南的通常结构大致为:
23 |
24 | - 简介
25 | - 大量优质的学习材料链接
26 | - 我自己整理的结构化知识体系
27 |
28 | 具体参考 [学习指南模板](/study/study-guild-abstraction)
29 |
30 | ## 关于学习指南系列
31 |
32 | ### 背景
33 |
34 | 现在互联网资讯很发达,网络上系统的教程很多,
35 | 我没必要重复造轮子。(我也没这个本事呀 >\_<)
36 |
37 | 不过话说回来,
38 | 作为前端开发者,有谁入门 JS 的时候是直接从 [ECMA-262 官方文档](https://www.ecma-international.org/publications/standards/Ecma-262.htm) 开始的吗…
39 | 至少也是从 [JavaScript - MDN](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript)、[JavaScript 标准参考教程](https://javascript.ruanyifeng.com/) 这样量级的简化版开始的。
40 |
41 | 但是这些文档怎么刷,哪些重点刷,刷完就够了么?
42 | (比如 JS 里的 [BigInt](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/BigInt) 是关键知识点吗)
43 |
44 | 这就引出了一个问题:
45 |
46 | > 在学习某个技能的时候,以什么方式从 0 到 1?(之后再从 1 到 Infinity)
47 |
48 | 对我来说,学习的难点不完全在于理解和掌握知识本身。
49 | 更重要的是,如何尽可能地花**更少的时间**理解**最核心的本质**并优先掌握**最实用的部分**。
50 |
51 | 现代化前端开发早已规模化和规范化,需要掌握的技能和工具层出不穷。
52 | 从经济角度看,不可能先花三年五年"精通"所有相关技术再创造工作价值。
53 | (何况说不定技术都更替了…)
54 | 并且在前端以外,还有那么多技术栈,以及丰富多彩的人类社会活动。
55 | 人生苦短 ~~我应该用 Python?~~
56 |
57 | 我希望能够提高自己的成长速度,来面对这一状况。
58 | 我想,应该有一个合适的方法论来解答这个问题。
59 |
60 | ### 方法
61 |
62 | 基于上述种种,我逐渐学习和整理出了一个[方法论](/study/crash-course-study-skills):
63 | 对于学习任意工具,都能以某种[通用的套路](/study/study-guild-abstraction)完成,
64 | 并且尽可能地理解和掌握最核心的部分。(而不是只学会调 API)
65 | (也就是先解决所谓最难的从 0 到 1 的部分)
66 |
67 | 当完成了一定量基础训练后,形成了良好的技术储备和直觉,
68 | 余下的道路便会在前方自动呈现。
69 | 就有把握解决实际业务中碰到的更多更琐碎和具体的问题了。
70 |
71 | 当大致能够独立完成开发链路的大部分环节,
72 | 这时候,才是专攻和精进某些细分方向的好时机了。
73 |
74 | ### 目的
75 |
76 | 作为该方法论中的一部分,
77 | 我应该将一些内容整理成可查询和迭代的文档体系,
78 | 并且根据方法论的原则,只覆盖我理解的最核心的知识。
79 |
80 | 所以,我开始写"学习指南"系列。
81 | 这个系列基本的目标是:
82 |
83 | - 从 0 入门,并且只包含关键信息
84 | - 以此作为我自己知识体系的梳理
85 | - (能帮助释放我的工作记忆)
86 |
87 | * 顺便的,将经验分享给我的朋友和同事们
88 | * 再顺便的,可能有机会帮助到曾经和我一样迷茫的初学者们。
89 |
90 | 如果你已经学会了某些技术,心想:"我的~~画风~~技术在你之上"
91 | 那么我的这些经验对你来说或许就意义不大了~(毕竟定位差异)
92 | (但一般都会有进阶的部分,我觉得也还是值得一看的…)
93 |
94 | 做了一点微小的工作,谢谢:)
95 |
96 | ## 资料
97 |
98 | ### 我的其他文章
99 |
100 | - [学习方法论](/study/crash-course-study-skills)
101 | - [学习指南模板](/study/study-guild-abstraction)
102 | - [计算机科学入门指南](/cs/crash-course-computer-science)
103 |
104 | ### 学习编程的合理方式
105 |
106 | - [When and why to clean up your code: now, later, never](https://codewithoutrules.com/2018/11/02/when-clean-up-your-code/)
107 | - [我如何零基础转行成为一个自信的前端](https://www.yuque.com/fe9/basic/mchxkr)
108 | - [聊聊 2018 年我所不了解的技术](https://overreacted.io/zh-hans/things-i-dont-know-as-of-2018/)
109 | - [Why I'm so good at coding.](https://www.youtube.com/watch?v=xqgH9j3x2OE)
110 | - [My Story of Being a Self Taught Programmer (Plus Tips and Advice!)](https://www.youtube.com/watch?v=62tsiY5j4_0)
111 |
--------------------------------------------------------------------------------
/docs/note/99.about/about-the-site.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 关于本站
3 | date: 2019-12-30 13:52:12
4 | permalink: /about/the-site
5 | categories:
6 | - 关于
7 | tags:
8 | -
9 | ---
10 |
11 | # 关于本站
12 |
13 | ## 系列文章
14 |
15 | 主要在写一些系列文章(更新中):
16 |
17 | - [前端入门指南系列](/note/frontend-development-cookbook)
18 | - [JavaScript 语言学习系列](/frontend/javascript-foundation)
19 | - [其他学习指南系列](/study/crash-course-study-skills)
20 |
21 | 还有一些其他的杂记。
22 |
23 | ## 特色
24 |
25 | - **从零入行前端开发**的学习路线
26 | - 推荐了**大量优秀学习教材**,形式包括视频、文档、书籍、笔记、题库
27 | - **拓宽视野,由浅入深**
28 |
29 | ## 支持
30 |
31 | 如果喜欢我的文章,可以 [到我的 GitHub 点个 ★ Star](https://github.com/seognil/fe-foundation) 支持一下 🎉
32 |
33 | ## 小记
34 |
35 | 近年来,前端已从最早的玩具发展为成体系的系统工程开发,
36 | 逐步赶上了传统软件开发和编程领域的步伐。
37 |
38 | 现在做前端开发,在真正开始写第一行业务代码之前,
39 | 需要很多前置的技术储备,并学习很多工具。
40 |
41 | 前端内的技术教程千千万,
42 | ~~(比如之前在掘金,关于 EventLoop 的文章每个月看到八百遍)~~
43 | 但是我 _很少_ 看到国内有文章系统地介绍:
44 | 一个现代化的前端工程应该从哪里开始入门和起步,
45 | 在前端体系之外、之前,应该要做,或最好要做什么事情。
46 | 在前端体系之后,还可以做哪些事情,向何处发展。
47 |
48 | 本系列根据我的工作经历,以及各路资料整理而成。
49 | 目标是,在有限的篇幅中,对前端开发的职业规划做一个向导,
50 | 一个只有一台干净电脑(Mac)的新手,如何从零学习并从事前端开发的工作。
51 |
52 | 所基于的开发环境是 MacOS。
53 | (Windows 和 Linux 有部分是相同的,另一部分是有替代方案的)
54 |
55 | 当然,有很多更全面的资料,
56 | 比我有限的人生经验不知道高到哪里去了,
57 | 这些参考资料的链接对应地分散在各个章节中。
58 | 希望对各位读者有所帮助。
59 |
60 | 根据自己的实际情况,**学以致用,循序渐进**,这是坠吼的。
61 |
62 | > —— 此系列写给我的朋友 东神、阿辉
63 |
--------------------------------------------------------------------------------
/docs/note/99.about/ref.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Mantras
3 | date: 2019-08-08 18:36:05
4 | permalink: /about/ref.html
5 | categories:
6 | - 草稿
7 | tags:
8 | -
9 | ---
10 |
11 | ## Mantras
12 |
13 | > Every Expert Was Once A Beginner.
14 |
15 | > Sic Parvis Magna
16 | > -- Uncharted 4: A Thief's End (2016)
17 |
18 | > Do not be sorry. Be better.
19 | > -- God Of War (2018)
20 |
21 | > a delayed game is eventually good, but a rushed game is forever bad.
22 | > -- Shigeru Miyamoto 宮本 茂
23 |
24 | > 枯れた技術の水平思考
25 | > -- Gunpei Yokoi 横井 軍平
26 |
27 | > Victory Loves Preparation
28 | > -- The Mechanic (2011)
29 |
30 | > Fortis Fortuna Adiuvat
31 | > -- John Wick (2014)
32 |
33 | > Art is pain, life is suffering.
34 | > -- John Wick 3 (2019)
35 |
36 | > Judge less, Observe more
37 |
38 | > The journey is hard and joyful.
39 | > -- HUAWEI
40 |
41 | > Stay hungry, stay foolish
42 | > -- Steve Jobs
43 |
44 | > KEEP CALM AND CALM DOWN
45 |
46 | > 取法其上,得乎其中。取法其中,得乎其下。
47 | > -- 孔子
48 |
49 | > Plato is dear to me, but dearer still is truth.
50 | > -- Aristotle
51 |
52 | > Always learn from the best!
53 |
54 | > Happy Smart Useful
55 | > -- https://sivers.org/hsu
56 |
57 | > Environment Body Mind
58 | > -- https://qotoqot.com/blog/improving-focus/
59 |
60 | > I hear & I forget. I see & I remember. I do & I understand.
61 |
62 | > Fail Fast, Fail Cheap, Move On.
63 |
64 | > MAKE EPIC SHIT
65 | > -- Evan You
66 |
67 | > Coding With Good Taste
68 | > -- Linus Torvalds
69 |
70 | > Write code that is easy to delete, not easy to extend.
71 | > -- https://programmingisterrible.com/
72 |
73 | > If you're willing to restrict the flexibility of your approach,
74 | > you can almost always do something better.
75 | > -- John Carmack
76 |
77 | ## 资料(未整理)
78 |
79 | [npm rank](https://gist.github.com/anvaka/8e8fa57c7ee1350e3491)
80 |
81 | [JavaScript 算法与数据结构](https://github.com/trekhleb/javascript-algorithms/blob/master/README.zh-CN.md)
82 | [LeetCode](https://leetcode.com)
83 |
84 | [前端面试每日 3+1(每日三问)](https://github.com/haizlin/fe-interview/blob/master/category/history.md)
85 | [MuYunyun/blog](https://github.com/MuYunyun/blog)
86 |
--------------------------------------------------------------------------------
/docs/note/frontend-development-cookbook.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 我的 Web 前端开发知识体系 (2022)
3 | date: 2022-01-29 17:46:00
4 | permalink: /note/frontend-development-cookbook
5 | categories:
6 | - 草稿
7 | tags:
8 | - awesome
9 | ---
10 |
11 | # 我的 Web 前端开发知识体系 (2022) {.cookbook-page}
12 |
13 | ---
14 |
15 | ## 写在前面
16 |
17 | ### Roadmap 资源和技术趋势
18 |
19 | - [JavaScript Rising Stars](https://risingstars.js.org/)
20 | - [Frontend Developer Roadmap](https://roadmap.sh/frontend)
21 | - [State Of JS](https://stateofjs.com/)
22 | - [State Of CSS](https://stateofcss.com/)
23 | - [Web Development In 2022 - A Practical Guide](https://www.youtube.com/watch?v=EqzUcMzfV1w)
24 | - [Programming & Web Development Crash Courses - Traversy Media](https://www.youtube.com/playlist?list=PLillGF-RfqbYeckUaD1z6nviTp31GLTH8)
25 |
26 | ### 我的索引
27 |
28 | - [装了啥](/workspace/awesome-tools)
29 | - [我都从哪学习](/study/where-do-i-learn-from)
30 | - [看了啥](/study/my-reading-list/)
31 | - [学习技巧](/study/crash-course-study-skills)
32 | - [英语](/study/using-english)
33 |
34 | ### 基本开发环境
35 |
36 | - [Mac](/workspace/mac)
37 | - [Chrome](/workspace/chrome)
38 | - [VS Code](/workspace/vscode)
39 |
40 | ## Web 前端
41 |
42 | - [硬核前端(劝退篇)](/frontend/frontend-hardcore-overview)
43 |
44 | ### 前端技术基础
45 |
46 | - [HTML](/frontend/html)
47 | - [CSS](/frontend/css)
48 | - [JavaScript](/cs/javascript-language-basic)
49 | - [TypeScript](/cs/typescript-language-basic)
50 | - [Node.js](/frontend/nodejs-basic)
51 |
52 | ### JavaScript
53 |
54 | - [JavaScript 学习指南 \*](/frontend/javascript-foundation)
55 | - [JavaScript 简介](/frontend/introduction-to-javascript)
56 | - [运行 JavaScript 代码的十几种方式](/frontend/how-to-run-javascript-code)
57 | - [JavaScript 进阶指南 \*](/frontend/javascript-advanced)
58 | - [语法糖、操作符、关键字、特性](/frontend/syntactic-sugar-in-javascript)
59 | - [前端模块化](/frontend/javascript-modules)
60 | - [正则表达式 学习指南](/frontend/javascript-regular-expression)
61 | - [JS Foundation \*](/frontend/javascript-foundation-legacy-version)
62 |
63 | ### npm 和工具
64 |
65 | - [npm](/frontend/introduction-to-npm)
66 | - [用 Proxy 进一步提高 npm 安装速度](/frontend/speeding-up-npm-install)
67 | - [使用 verdaccio 搭建私有 npm 仓库](/frontend/set-up-a-private-npm-registry-using-verdaccio)
68 |
69 | ### React/脚手架
70 |
71 | - [React](/frontend/react-hooks)
72 | - Vite
73 | - Next.js
74 |
75 | ### 规范化
76 |
77 | - ES Lint
78 | - Prettier
79 | - tsconfig.json
80 | - Husky
81 |
82 | ### 状态管理工具
83 |
84 | - Recoil.js
85 | - Mobx
86 | - [RxJS](/frontend/rxjs)
87 | - [Redux](/frontend/redux)
88 |
89 | ### CSS 工具
90 |
91 | - Tailwind / Twind
92 | - @emotion/css
93 |
94 | ### 测试
95 |
96 | - Playwright
97 | - [Jest](/frontend/jest)
98 | - [testing-library](/frontend/testing-library)
99 | - [Cypress](/frontend/cypress)
100 |
101 | ### 部署
102 |
103 | - Github
104 | - Vercel
105 |
106 | ## 其他
107 |
108 | ### 计算机科学
109 |
110 | - [计算机科学](/cs/crash-course-computer-science)
111 | - [函数式编程](/cs/introduction-to-functional-programming)
112 | - 数据结构/算法
113 | - 设计模式
114 |
115 | ### 实用工具
116 |
117 | - [Git](/cs/git)
118 | - [Markdown](/cs/markdown)
119 | - [终端](/workspace/introduction-to-terminal)
120 | - [打造趁手的终端](/workspace/terminal-settings)
121 | - [Python](/cs/python-language-basic)
122 |
123 | ### 杂谈
124 |
125 | - [游戏环境研究笔记(2022-01)](/misc/gaming-set/)
126 | - [用快捷键控制视频播放](/workspace/my-video-player-shortcuts)
127 | - [代码行数统计工具小测](/cs/count-lines-of-code)
128 | - [Ubuntu 服务器基本防护](/misc/linux-basic-security)
129 | - [如何清洁机械键盘](/misc/clean-a-keyboard)
130 | - [关于学习指南系列](/about/the-guild)
131 | - [杂谈:你可学点好吧](/study/dont-waste-your-time-and-money)
132 | - [杂谈:我们为什么需要读书和学习](/study/why-we-need-to-study)
133 | - [关于学习的鸡汤](/study/study-fortune)
134 |
135 | ## 你可以看什么大佬
136 |
137 | - [Anthony Fu](https://github.com/antfu)
138 | - [EGOIST](https://github.com/egoist)
139 | - [Sindre Sorhus](https://github.com/sindresorhus)
140 |
141 | ### (Phodal 写的系列文章)
142 |
143 | - [黄峰达(Phodal Huang) 是谁](https://www.phodal.com/about/)
144 |
145 | * [Phodal's Idea 实战指南](http://ideabook.phodal.com/)
146 | * [GitHub 漫游指南](http://github.phodal.com/)
147 | * [Growth - an app to help you Be Awesome Developer](http://growth.ren/)
148 | * [Growth: 全栈增长工程师指南](https://growth.phodal.com/)
149 | * [Growth: 全栈增长工程师实战](http://growth-in-action.phodal.com/)
150 | * [RePractise](http://repractise.phodal.com/)
151 | * [我的职业是前端工程师](https://ued.party/)
152 | * [Serverless 应用开发指南](http://serverless.ink/)
153 | * [写给软件工程师看的硬件编程指南](https://phodal.github.io/make/)
154 | * [Thinking in Microfrontend (微前端的那些事儿)](https://microfrontends.cn/)
155 | * [系统重构与迁移指南](https://migration.ink/)
156 | * [Developer 进阶书单](https://phodal.github.io/booktree/)
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
183 |
--------------------------------------------------------------------------------
/google3ceb9a355a21cbf4.html:
--------------------------------------------------------------------------------
1 | google-site-verification: google3ceb9a355a21cbf4.html
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "fe-foundation",
3 | "version": "0.0.0",
4 | "description": "",
5 | "license": "MIT",
6 | "author": "seognil",
7 | "repository": "seognil/fe-foundation",
8 | "publishConfig": {
9 | "registry": "https://prevent.push.to.registry/"
10 | },
11 | "keywords": [],
12 | "bugs": "https://github.com/seognil/fe-foundation/issues",
13 | "homepage": "https://github.com/seognil/fe-foundation",
14 | "scripts": {
15 | "build": "vuepress build ./docs",
16 | "dev": "vuepress dev ./docs",
17 | "start": "npm run dev",
18 | "preview": "npm run build && serve ./public",
19 | "check-md": "tsup scripts/check-broken-links.ts && node dist/check-broken-links.js",
20 | "redirect": "tsup scripts/update-config-files.ts && node dist/update-config-files.js"
21 | },
22 | "dependencies": {
23 | "dayjs": "^1.11.6",
24 | "markdown-it-attrs": "^4.1.4",
25 | "transliteration": "^2.3.5",
26 | "vuepress": "^1.9.7",
27 | "vuepress-plugin-medium-zoom": "^1.1.9",
28 | "vuepress-plugin-zooming": "^1.1.8",
29 | "vuepress-theme-vdoing": "^1.12.8"
30 | },
31 | "devDependencies": {
32 | "@types/markdown-it-attrs": "^4.1.0",
33 | "@types/node": "^17.0.45",
34 | "@types/prettier": "^2.7.1",
35 | "chalk": "^5.1.2",
36 | "globby": "^12.2.0",
37 | "https-proxy-agent": "^5.0.1",
38 | "node-fetch": "^3.3.0",
39 | "ora": "^6.1.2",
40 | "p-limit": "^4.0.0",
41 | "prettier": "^2.7.1",
42 | "prettier-plugin-organize-imports": "^2.3.4",
43 | "serve": "^13.0.4",
44 | "tsup": "^5.12.9",
45 | "typescript": "^4.9.3"
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/scripts/301-record.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * first route is the latest route
3 | *
4 | * [
5 | * to:
6 | * from:
7 | * from:
8 | * ]
9 | *
10 | */
11 | export const redirectRecords: string[][] = [
12 | // * ----------------
13 |
14 | [
15 | //
16 | '/note/frontend-development-cookbook',
17 | '/note/fe-development-cookbook-old',
18 | '/note/fe-development-cookbook',
19 | '/note/frontend-development-cookbook.html',
20 | ],
21 |
22 | // * ---------------- study
23 |
24 | [
25 | //
26 | '/study/where-do-i-learn-from',
27 | '/about/where-do-i-learn-from',
28 | '/note/my-reading.html',
29 | ],
30 |
31 | // * ---------------- study
32 |
33 | [
34 | //
35 | '/study/crash-course-study-skills',
36 | '/note/study-methodology.html',
37 | ],
38 |
39 | [
40 | //
41 | '/study/using-english',
42 | '/note/english-using.html',
43 | ],
44 | [
45 | //
46 | '/study/study-fortune',
47 | '/note/study-fortune.html',
48 | ],
49 | [
50 | //
51 | '/study/study-guild-abstraction',
52 | '/note/study-guild-abstraction.html',
53 | ],
54 | [
55 | //
56 | '/study/why-we-need-to-study',
57 | '/study/study-the-only-way',
58 | '/note/study-the-only-way.html',
59 | ],
60 | [
61 | //
62 | '/study/dont-waste-your-time-and-money',
63 | '/study/study-the-costly-way',
64 | '/note/study-the-costly-way.html',
65 | ],
66 |
67 | // * ---------------- workspace
68 |
69 | [
70 | //
71 | '/workspace/awesome-tools',
72 | '/note/my-workstation.html',
73 | ],
74 | [
75 | //
76 | '/workspace/mac',
77 | '/note/mac.html',
78 | ],
79 | [
80 | //
81 | '/workspace/chrome',
82 | '/note/chrome.html',
83 | ],
84 | [
85 | //
86 | '/workspace/vscode',
87 | '/note/vscode.html',
88 | ],
89 | [
90 | //
91 | '/workspace/introduction-to-terminal',
92 | '/note/terminal-intro.html',
93 | ],
94 | [
95 | //
96 | '/workspace/terminal-settings',
97 | '/note/terminal-config.html',
98 | ],
99 | [
100 | //
101 | '/workspace/my-video-player-shortcuts',
102 | '/note/video-hotkey.html',
103 | ],
104 |
105 | // * ---------------- cs
106 |
107 | [
108 | //
109 | '/cs/crash-course-computer-science',
110 | '/note/computer-science.html',
111 | ],
112 | [
113 | //
114 | '/cs/introduction-to-functional-programming',
115 | '/note/functional-programming.html',
116 | ],
117 | [
118 | //
119 | '/cs/git',
120 | '/note/git.html',
121 | ],
122 | [
123 | //
124 | '/cs/markdown',
125 | '/note/markdown.html',
126 | ],
127 | [
128 | //
129 | '/cs/count-lines-of-code',
130 | '/note/cloc.html',
131 | ],
132 | [
133 | //
134 | '/cs/javascript-language-basic',
135 | '/note/js-basic',
136 | ],
137 | [
138 | //
139 | '/cs/typescript-language-basic',
140 | '/note/typescript.html',
141 | ],
142 | [
143 | //
144 | '/cs/python-language-basic',
145 | '/note/python-language-basic',
146 | ],
147 |
148 | // * ---------------- frontend
149 |
150 | [
151 | //
152 | '/frontend/frontend-hardcore-overview',
153 | '/note/fe-hardcore-overview.html',
154 | ],
155 | [
156 | //
157 | '/frontend/html',
158 | '/note/html.html',
159 | ],
160 | [
161 | //
162 | '/frontend/css',
163 | '/note/css.html',
164 | ],
165 | [
166 | //
167 | '/frontend/javascript-foundation',
168 | '/note/js-foundation.html',
169 | ],
170 | [
171 | //
172 | '/frontend/introduction-to-javascript',
173 | '/note/js-intro.html',
174 | ],
175 | [
176 | //
177 | '/frontend/how-to-run-javascript-code',
178 | '/note/how-to-run-js.html',
179 | ],
180 | [
181 | //
182 | '/frontend/javascript-advanced',
183 | '/note/js-advanced.html',
184 | ],
185 | [
186 | //
187 | '/frontend/syntactic-sugar-in-javascript',
188 | '/note/syntactic-sugar.html',
189 | ],
190 | [
191 | //
192 | '/frontend/javascript-modules',
193 | '/note/js-modular.html',
194 | ],
195 | [
196 | //
197 | '/frontend/javascript-regular-expression',
198 | '/note/regexp.html',
199 | ],
200 | [
201 | //
202 | '/frontend/javascript-foundation-legacy-version',
203 | '/note/js-foundation-old.html',
204 | ],
205 | [
206 | //
207 | '/frontend/nodejs-basic',
208 | '/note/node-basic.html',
209 | ],
210 | [
211 | //
212 | '/frontend/introduction-to-npm',
213 | '/note/npm-overview.html',
214 | ],
215 | [
216 | //
217 | '/frontend/speeding-up-npm-install',
218 | '/note/npm-speedup.html',
219 | ],
220 | [
221 | //
222 | '/frontend/set-up-a-private-npm-registry-using-verdaccio',
223 | '/note/npm-verdaccio.html',
224 | ],
225 | [
226 | //
227 | '/frontend/rxjs',
228 | '/note/rxjs.html',
229 | ],
230 | [
231 | //
232 | '/frontend/redux',
233 | '/note/redux.html',
234 | ],
235 | [
236 | //
237 | '/frontend/react-hooks',
238 | '/note/react-hooks.html',
239 | ],
240 | [
241 | //
242 | '/frontend/redux-observable',
243 | '/note/redux-observable.html',
244 | ],
245 | [
246 | //
247 | '/frontend/jest',
248 | '/note/jest.html',
249 | ],
250 | [
251 | //
252 | '/frontend/testing-library',
253 | '/note/testing-library.html',
254 | ],
255 | [
256 | //
257 | '/frontend/cypress',
258 | '/note/cypress.html',
259 | ],
260 |
261 | // * ---------------- misc
262 |
263 | [
264 | //
265 | '/misc/linux-basic-security',
266 | '/note/linux-basic-security.html',
267 | ],
268 | [
269 | //
270 | '/misc/clean-a-keyboard',
271 | '/note/clean-keyboard.html',
272 | ],
273 |
274 | // * ---------------- about
275 |
276 | [
277 | //
278 | '/about/the-site',
279 | '/note/readme.html',
280 | ],
281 | [
282 | //
283 | '/about/me',
284 | '/about/',
285 | ],
286 | [
287 | //
288 | '/about/the-guild',
289 | '/note/about-the-guild.html',
290 | ],
291 | ];
292 |
--------------------------------------------------------------------------------
/scripts/check-broken-links.ts:
--------------------------------------------------------------------------------
1 | import chalk from 'chalk';
2 | import { readFile } from 'fs/promises';
3 | import { globbySync } from 'globby';
4 | import HttpsProxyAgent from 'https-proxy-agent';
5 | import fetch from 'node-fetch';
6 | import ora from 'ora';
7 | import pLimit from 'p-limit';
8 | import { resolve } from 'path';
9 |
10 | const { blue, red, yellow } = chalk;
11 |
12 | const projRoot = resolve(process.cwd());
13 |
14 | const files = globbySync('docs/**/*.md', { cwd: projRoot }).filter((e) => !e.includes('@pages'));
15 |
16 | // * ================================================================================
17 |
18 | interface ParseUnit {
19 | mdlink: string;
20 | text: string;
21 | url: string;
22 | source: string;
23 | }
24 |
25 | const task = async () => {
26 | const contents = await Promise.all(
27 | files.map(async (e) => {
28 | const source = resolve(projRoot, e);
29 | const content = await readFile(source, { encoding: 'utf8' });
30 | return { content, source };
31 | }),
32 | );
33 |
34 | // * ----------------
35 |
36 | const permalinks = contents
37 | .map(({ content }) => content.match(/\npermalink: (.*)\n/)?.[1])
38 | .filter((e) => e);
39 |
40 | // * ----------------
41 |
42 | const flattenLinks: ParseUnit[] = contents
43 | .map(({ content, source }) => {
44 | return { source, mdlinks: [...(content.match(/\[[^\]]+\]\([^\)]+\)/g) ?? [])] };
45 | })
46 | .map(({ source, mdlinks }) => mdlinks.map((mdlink) => ({ mdlink, source })))
47 | .flat(1)
48 | .map(({ mdlink, source }) => {
49 | const [_, text, url] = mdlink.match(/\[([^\]]+)\]\(([^\)]+)\)/)!;
50 | return { mdlink, text, url, source };
51 | })
52 | .sort((a, b) => (a.url < b.url ? -1 : 1));
53 |
54 | const allLinks = Array.from(new Set(flattenLinks.map((e) => e.url)));
55 |
56 | const httpLinks = allLinks.filter((e) => /^https?:/.test(e));
57 | const anchorLinks = allLinks.filter((e) => /^#/.test(e));
58 | const mdLinks = allLinks.filter((e) => /^\//.test(e));
59 | const mdPureLinks = mdLinks.map((e) => e.replace(/#.*/, ''));
60 | const otherLinks = allLinks
61 | .filter((e) => !httpLinks.includes(e))
62 | .filter((e) => !anchorLinks.includes(e))
63 | .filter((e) => !mdPureLinks.includes(e));
64 |
65 | console.log('other links ----------------', otherLinks);
66 |
67 | // console.log('other links ----------------', anchorLinks);
68 |
69 | // * ---------------- md pure links check
70 |
71 | const badMdLinks = mdPureLinks.filter((e) => !permalinks.includes(e));
72 | error(badMdLinks, flattenLinks);
73 |
74 | // * ---------------- http links check
75 |
76 | // await checkHtml(httpLinks, flattenLinks);
77 | };
78 |
79 | // * ----------------------------------------------------------------
80 |
81 | task();
82 |
83 | // * ================================================================================
84 |
85 | const error = (urls: string[], flattenLinks: ParseUnit[]) => {
86 | const list = urls.map((url) => flattenLinks.find((e) => e.url === url));
87 | console.log('bad links ----------------');
88 | list.forEach((e) => console.warn(`${blue(e?.source)}: ${red(e?.mdlink)}`));
89 | };
90 |
91 | // * ================================================================================
92 |
93 | const checkHtml = async (urls: string[], flattenLinks: ParseUnit[]) => {
94 | const limit = pLimit(8);
95 |
96 | const spinner = ora('Checking Urls').start();
97 |
98 | const proxyAgent = HttpsProxyAgent(process.env.ALL_PROXY!);
99 |
100 | console.log('bad links ----------------');
101 |
102 | await Promise.all(
103 | urls
104 | .sort(() => Math.random() - 0.5)
105 | // .slice(0, 5)
106 | .map((url) =>
107 | limit(async () => {
108 | spinner.text = url;
109 | return fetch(url, { agent: proxyAgent })
110 | .then((res) => {
111 | const code = res.status;
112 | const result = { url, code };
113 |
114 | // * asap // Seognil LC 2021/09/30
115 | if (code !== 200) {
116 | spinner.text = '';
117 | spinner.render();
118 |
119 | const e = flattenLinks.find((e) => e.url === url);
120 | console.log(`${blue(e?.source)}: ${red(e?.mdlink)} - ${yellow(code)}`);
121 |
122 | spinner.text = url;
123 | }
124 |
125 | return result;
126 | })
127 | .catch((err) => {
128 | spinner.text = '';
129 | spinner.render();
130 |
131 | const e = flattenLinks.find((e) => e.url === url);
132 | console.log(`${blue(e?.source)}: ${red(e?.mdlink)} - ${yellow(err)}`);
133 |
134 | spinner.text = url;
135 | return null;
136 | });
137 | }),
138 | ),
139 | );
140 |
141 | spinner.stop();
142 | };
143 |
--------------------------------------------------------------------------------
/scripts/list-notes.ts:
--------------------------------------------------------------------------------
1 | import { readFile } from 'node:fs/promises';
2 | import { join, relative } from 'node:path';
3 | import { globby } from 'globby';
4 |
5 | const docDir = join(__dirname, '../docs/');
6 |
7 | const files = await globby(join(docDir, 'note/**/*.md'));
8 |
9 | const getTitleAndLink = async (filePath: string) => {
10 | const content = await readFile(filePath, 'utf-8');
11 |
12 | const headPieces = content.split('\n').slice(0, 5).join('\n');
13 | const title = headPieces.match(/title:\s?(.*)/)?.[1];
14 | const permalink = headPieces.match(/permalink:\s?(.*)/)?.[1];
15 | const relativePath = relative(docDir, filePath);
16 | return { title, permalink, filePath, relativePath };
17 | };
18 |
19 | const titleAndLines = await Promise.all(files.map(getTitleAndLink));
20 |
21 | console.log(titleAndLines.map(({ title, permalink }) => `[${title}](${permalink})`).join('\n'));
22 |
--------------------------------------------------------------------------------
/scripts/update-config-files.ts:
--------------------------------------------------------------------------------
1 | import { writeFileSync } from 'fs';
2 | import { resolve } from 'path';
3 | import { redirectRecords } from './301-record';
4 |
5 | // * ================================================================================
6 |
7 | const projRoot = resolve(process.cwd());
8 |
9 | // * ================================================================================
10 |
11 | interface FlattenRedirect {
12 | to: string;
13 | from: string;
14 | }
15 |
16 | const flattenList: FlattenRedirect[] = redirectRecords
17 | .sort((a, b) => (a[0] < b[0] ? -1 : 1))
18 | .map((routes) => {
19 | const [to, ...from] = routes;
20 | return from
21 | .sort((a, b) => (a < b ? -1 : 1))
22 | .map((oldUrl) => [
23 | { to, from: oldUrl + '.html' },
24 | { to, from: oldUrl },
25 | ]);
26 | })
27 | .flat(2)
28 | .map(({ to, from }) => ({ to, from: from.replace('/.html', '/index.html') }))
29 | .filter((e) => !e.from.includes('.html.html'))
30 | .filter((e) => e.to !== e.from);
31 |
32 | // * ---------------------------------------------------------------- vue
33 |
34 | interface VuepressRedirect {
35 | path: string;
36 | redirect: string;
37 | }
38 |
39 | const vueRedirectList: VuepressRedirect[] = flattenList.map(({ to, from }) => ({
40 | path: from,
41 | redirect: to,
42 | }));
43 |
44 | writeFileSync(
45 | resolve(projRoot, './docs/.vuepress/vue-redirect.js'),
46 | `module.exports = ${JSON.stringify(vueRedirectList, null, 2)}`,
47 | );
48 |
49 | // * ---------------------------------------------------------------- public
50 |
51 | const _redirects = flattenList.map(({ from, to }) => `${from} ${to} 301`).join('\n');
52 | writeFileSync(resolve(projRoot, './docs/.vuepress/public/_redirects'), _redirects);
53 |
54 | // * ---------------------------------------------------------------- vercel
55 |
56 | const vercelJson = JSON.stringify(
57 | {
58 | github: { silent: true },
59 | redirects: flattenList.map(({ from, to }) => ({
60 | source: from,
61 | destination: to,
62 | statusCode: 301,
63 | })),
64 | },
65 | null,
66 | 2,
67 | );
68 | writeFileSync(resolve(projRoot, './vercel.json'), vercelJson);
69 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "module": "esnext",
5 | "jsx": "preserve",
6 | "moduleResolution": "node",
7 | "strict": true,
8 | "alwaysStrict": true,
9 | "noImplicitAny": true,
10 | "noImplicitThis": true,
11 | "noImplicitReturns": true,
12 | "esModuleInterop": true,
13 | "declaration": true,
14 | "sourceMap": true,
15 | },
16 | }
--------------------------------------------------------------------------------
/vercel.json:
--------------------------------------------------------------------------------
1 | {
2 | "github": {
3 | "silent": true
4 | },
5 | "redirects": [
6 | {
7 | "source": "/about/index.html",
8 | "destination": "/about/me",
9 | "statusCode": 301
10 | },
11 | {
12 | "source": "/about/",
13 | "destination": "/about/me",
14 | "statusCode": 301
15 | },
16 | {
17 | "source": "/note/about-the-guild.html",
18 | "destination": "/about/the-guild",
19 | "statusCode": 301
20 | },
21 | {
22 | "source": "/note/readme.html",
23 | "destination": "/about/the-site",
24 | "statusCode": 301
25 | },
26 | {
27 | "source": "/note/cloc.html",
28 | "destination": "/cs/count-lines-of-code",
29 | "statusCode": 301
30 | },
31 | {
32 | "source": "/note/computer-science.html",
33 | "destination": "/cs/crash-course-computer-science",
34 | "statusCode": 301
35 | },
36 | {
37 | "source": "/note/git.html",
38 | "destination": "/cs/git",
39 | "statusCode": 301
40 | },
41 | {
42 | "source": "/note/functional-programming.html",
43 | "destination": "/cs/introduction-to-functional-programming",
44 | "statusCode": 301
45 | },
46 | {
47 | "source": "/note/js-basic.html",
48 | "destination": "/cs/javascript-language-basic",
49 | "statusCode": 301
50 | },
51 | {
52 | "source": "/note/js-basic",
53 | "destination": "/cs/javascript-language-basic",
54 | "statusCode": 301
55 | },
56 | {
57 | "source": "/note/markdown.html",
58 | "destination": "/cs/markdown",
59 | "statusCode": 301
60 | },
61 | {
62 | "source": "/note/python-language-basic.html",
63 | "destination": "/cs/python-language-basic",
64 | "statusCode": 301
65 | },
66 | {
67 | "source": "/note/python-language-basic",
68 | "destination": "/cs/python-language-basic",
69 | "statusCode": 301
70 | },
71 | {
72 | "source": "/note/typescript.html",
73 | "destination": "/cs/typescript-language-basic",
74 | "statusCode": 301
75 | },
76 | {
77 | "source": "/note/css.html",
78 | "destination": "/frontend/css",
79 | "statusCode": 301
80 | },
81 | {
82 | "source": "/note/cypress.html",
83 | "destination": "/frontend/cypress",
84 | "statusCode": 301
85 | },
86 | {
87 | "source": "/note/fe-hardcore-overview.html",
88 | "destination": "/frontend/frontend-hardcore-overview",
89 | "statusCode": 301
90 | },
91 | {
92 | "source": "/note/how-to-run-js.html",
93 | "destination": "/frontend/how-to-run-javascript-code",
94 | "statusCode": 301
95 | },
96 | {
97 | "source": "/note/html.html",
98 | "destination": "/frontend/html",
99 | "statusCode": 301
100 | },
101 | {
102 | "source": "/note/js-intro.html",
103 | "destination": "/frontend/introduction-to-javascript",
104 | "statusCode": 301
105 | },
106 | {
107 | "source": "/note/npm-overview.html",
108 | "destination": "/frontend/introduction-to-npm",
109 | "statusCode": 301
110 | },
111 | {
112 | "source": "/note/js-advanced.html",
113 | "destination": "/frontend/javascript-advanced",
114 | "statusCode": 301
115 | },
116 | {
117 | "source": "/note/js-foundation.html",
118 | "destination": "/frontend/javascript-foundation",
119 | "statusCode": 301
120 | },
121 | {
122 | "source": "/note/js-foundation-old.html",
123 | "destination": "/frontend/javascript-foundation-legacy-version",
124 | "statusCode": 301
125 | },
126 | {
127 | "source": "/note/js-modular.html",
128 | "destination": "/frontend/javascript-modules",
129 | "statusCode": 301
130 | },
131 | {
132 | "source": "/note/regexp.html",
133 | "destination": "/frontend/javascript-regular-expression",
134 | "statusCode": 301
135 | },
136 | {
137 | "source": "/note/jest.html",
138 | "destination": "/frontend/jest",
139 | "statusCode": 301
140 | },
141 | {
142 | "source": "/note/node-basic.html",
143 | "destination": "/frontend/nodejs-basic",
144 | "statusCode": 301
145 | },
146 | {
147 | "source": "/note/react-hooks.html",
148 | "destination": "/frontend/react-hooks",
149 | "statusCode": 301
150 | },
151 | {
152 | "source": "/note/redux.html",
153 | "destination": "/frontend/redux",
154 | "statusCode": 301
155 | },
156 | {
157 | "source": "/note/redux-observable.html",
158 | "destination": "/frontend/redux-observable",
159 | "statusCode": 301
160 | },
161 | {
162 | "source": "/note/rxjs.html",
163 | "destination": "/frontend/rxjs",
164 | "statusCode": 301
165 | },
166 | {
167 | "source": "/note/npm-verdaccio.html",
168 | "destination": "/frontend/set-up-a-private-npm-registry-using-verdaccio",
169 | "statusCode": 301
170 | },
171 | {
172 | "source": "/note/npm-speedup.html",
173 | "destination": "/frontend/speeding-up-npm-install",
174 | "statusCode": 301
175 | },
176 | {
177 | "source": "/note/syntactic-sugar.html",
178 | "destination": "/frontend/syntactic-sugar-in-javascript",
179 | "statusCode": 301
180 | },
181 | {
182 | "source": "/note/testing-library.html",
183 | "destination": "/frontend/testing-library",
184 | "statusCode": 301
185 | },
186 | {
187 | "source": "/note/clean-keyboard.html",
188 | "destination": "/misc/clean-a-keyboard",
189 | "statusCode": 301
190 | },
191 | {
192 | "source": "/note/linux-basic-security.html",
193 | "destination": "/misc/linux-basic-security",
194 | "statusCode": 301
195 | },
196 | {
197 | "source": "/note/fe-development-cookbook.html",
198 | "destination": "/note/frontend-development-cookbook",
199 | "statusCode": 301
200 | },
201 | {
202 | "source": "/note/fe-development-cookbook",
203 | "destination": "/note/frontend-development-cookbook",
204 | "statusCode": 301
205 | },
206 | {
207 | "source": "/note/fe-development-cookbook-old.html",
208 | "destination": "/note/frontend-development-cookbook",
209 | "statusCode": 301
210 | },
211 | {
212 | "source": "/note/fe-development-cookbook-old",
213 | "destination": "/note/frontend-development-cookbook",
214 | "statusCode": 301
215 | },
216 | {
217 | "source": "/note/frontend-development-cookbook.html",
218 | "destination": "/note/frontend-development-cookbook",
219 | "statusCode": 301
220 | },
221 | {
222 | "source": "/note/study-methodology.html",
223 | "destination": "/study/crash-course-study-skills",
224 | "statusCode": 301
225 | },
226 | {
227 | "source": "/note/study-the-costly-way.html",
228 | "destination": "/study/dont-waste-your-time-and-money",
229 | "statusCode": 301
230 | },
231 | {
232 | "source": "/study/study-the-costly-way.html",
233 | "destination": "/study/dont-waste-your-time-and-money",
234 | "statusCode": 301
235 | },
236 | {
237 | "source": "/study/study-the-costly-way",
238 | "destination": "/study/dont-waste-your-time-and-money",
239 | "statusCode": 301
240 | },
241 | {
242 | "source": "/note/study-fortune.html",
243 | "destination": "/study/study-fortune",
244 | "statusCode": 301
245 | },
246 | {
247 | "source": "/note/study-guild-abstraction.html",
248 | "destination": "/study/study-guild-abstraction",
249 | "statusCode": 301
250 | },
251 | {
252 | "source": "/note/english-using.html",
253 | "destination": "/study/using-english",
254 | "statusCode": 301
255 | },
256 | {
257 | "source": "/about/where-do-i-learn-from.html",
258 | "destination": "/study/where-do-i-learn-from",
259 | "statusCode": 301
260 | },
261 | {
262 | "source": "/about/where-do-i-learn-from",
263 | "destination": "/study/where-do-i-learn-from",
264 | "statusCode": 301
265 | },
266 | {
267 | "source": "/note/my-reading.html",
268 | "destination": "/study/where-do-i-learn-from",
269 | "statusCode": 301
270 | },
271 | {
272 | "source": "/note/study-the-only-way.html",
273 | "destination": "/study/why-we-need-to-study",
274 | "statusCode": 301
275 | },
276 | {
277 | "source": "/study/study-the-only-way.html",
278 | "destination": "/study/why-we-need-to-study",
279 | "statusCode": 301
280 | },
281 | {
282 | "source": "/study/study-the-only-way",
283 | "destination": "/study/why-we-need-to-study",
284 | "statusCode": 301
285 | },
286 | {
287 | "source": "/note/my-workstation.html",
288 | "destination": "/workspace/awesome-tools",
289 | "statusCode": 301
290 | },
291 | {
292 | "source": "/note/chrome.html",
293 | "destination": "/workspace/chrome",
294 | "statusCode": 301
295 | },
296 | {
297 | "source": "/note/terminal-intro.html",
298 | "destination": "/workspace/introduction-to-terminal",
299 | "statusCode": 301
300 | },
301 | {
302 | "source": "/note/mac.html",
303 | "destination": "/workspace/mac",
304 | "statusCode": 301
305 | },
306 | {
307 | "source": "/note/video-hotkey.html",
308 | "destination": "/workspace/my-video-player-shortcuts",
309 | "statusCode": 301
310 | },
311 | {
312 | "source": "/note/terminal-config.html",
313 | "destination": "/workspace/terminal-settings",
314 | "statusCode": 301
315 | },
316 | {
317 | "source": "/note/vscode.html",
318 | "destination": "/workspace/vscode",
319 | "statusCode": 301
320 | }
321 | ]
322 | }
--------------------------------------------------------------------------------