├── site
├── static
│ └── .gitkeep
├── .eslintignore
├── build
│ ├── logo.png
│ ├── vue-loader.conf.js
│ ├── build.js
│ ├── check-versions.js
│ ├── webpack.base.conf.js
│ ├── utils.js
│ ├── webpack.dev.conf.js
│ └── webpack.prod.conf.js
├── config
│ ├── prod.env.js
│ ├── dev.env.js
│ └── index.js
├── src
│ ├── assets
│ │ └── logo.png
│ ├── components
│ │ ├── notFound.vue
│ │ ├── loading.vue
│ │ └── Index.vue
│ ├── router
│ │ └── index.js
│ ├── App.vue
│ └── main.js
├── .editorconfig
├── .gitignore
├── .babelrc
├── .postcssrc.js
├── README.md
├── .eslintrc.js
├── index.html
└── package.json
├── assets
├── dot.png
├── new.png
└── rss.gif
├── data
├── .rss.json.swp
├── tags.json
├── rss.json
└── links.json
├── server
├── once.js
├── package.json
├── app.js
├── utils.js
├── update.js
├── writemd.js
├── fetch.js
├── links.json
└── yarn.lock
├── details
├── tags
│ ├── oop.md
│ ├── git-svn.md
│ ├── job-interview.md
│ ├── vue.md
│ ├── 肺炎疫情.md
│ ├── typescript.md
│ ├── dev-mobile.md
│ ├── dev-game.md
│ ├── server.md
│ ├── miniprogram.md
│ ├── react.md
│ ├── front-end-advanced.md
│ ├── audio-video.md
│ ├── canvas-image.md
│ ├── optimization.md
│ ├── nodejs.md
│ ├── other.md
│ ├── pack-build.md
│ ├── browser.md
│ ├── css.md
│ └── javascript.md
└── 张鑫旭-鑫空间-鑫生活.md
├── package.json
├── now.json
├── .gitignore
├── templates
├── DETAILS.md
├── TAGS.md
├── TIMELINE.md
└── README.md
├── .github
└── workflows
│ └── main.yml
├── TIMELINE.md
├── TAGS.md
└── README.md
/site/static/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/dot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/w4ctech/front-end-rss/HEAD/assets/dot.png
--------------------------------------------------------------------------------
/assets/new.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/w4ctech/front-end-rss/HEAD/assets/new.png
--------------------------------------------------------------------------------
/assets/rss.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/w4ctech/front-end-rss/HEAD/assets/rss.gif
--------------------------------------------------------------------------------
/data/.rss.json.swp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/w4ctech/front-end-rss/HEAD/data/.rss.json.swp
--------------------------------------------------------------------------------
/site/.eslintignore:
--------------------------------------------------------------------------------
1 | /build/
2 | /config/
3 | /dist/
4 | /*.js
5 | /src/components/Index.vue
6 |
--------------------------------------------------------------------------------
/site/build/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/w4ctech/front-end-rss/HEAD/site/build/logo.png
--------------------------------------------------------------------------------
/site/config/prod.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | module.exports = {
3 | NODE_ENV: '"production"'
4 | }
5 |
--------------------------------------------------------------------------------
/site/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/w4ctech/front-end-rss/HEAD/site/src/assets/logo.png
--------------------------------------------------------------------------------
/server/once.js:
--------------------------------------------------------------------------------
1 | const handlerUpdate = require('./update')
2 |
3 | // node once.js 执行一次,手动更新
4 | handlerUpdate()
--------------------------------------------------------------------------------
/details/tags/oop.md:
--------------------------------------------------------------------------------
1 | :alarm_clock: 更新时间: 2025-12-13 23:00:43。[来源分类](../README.md)、[标签分类](../TAGS.md)、[时间分类](../TIMELINE.md)
2 |
3 | ## 面向对象❤️
4 |
5 |
6 | > 关键字:`面向对象`
7 |
8 |
9 |
--------------------------------------------------------------------------------
/details/tags/git-svn.md:
--------------------------------------------------------------------------------
1 | :alarm_clock: 更新时间: 2025-12-13 23:00:43。[来源分类](../README.md)、[标签分类](../TAGS.md)、[时间分类](../TIMELINE.md)
2 |
3 | ## Git、SVN
4 |
5 |
6 | > 关键字:`Git`、`SVN`
7 |
8 |
9 |
--------------------------------------------------------------------------------
/details/tags/job-interview.md:
--------------------------------------------------------------------------------
1 | :alarm_clock: 更新时间: 2025-12-13 23:00:43。[来源分类](../README.md)、[标签分类](../TAGS.md)、[时间分类](../TIMELINE.md)
2 |
3 | ## 招聘面试
4 |
5 |
6 | > 关键字:`招聘`、`面试`
7 |
8 |
9 |
--------------------------------------------------------------------------------
/details/tags/vue.md:
--------------------------------------------------------------------------------
1 | :alarm_clock: 更新时间: 2025-12-13 23:00:43。[来源分类](../README.md)、[标签分类](../TAGS.md)、[时间分类](../TIMELINE.md)
2 |
3 | ## Vue
4 |
5 |
6 | > 关键字:`Vue`、`ElementUI`
7 |
8 |
9 |
--------------------------------------------------------------------------------
/details/tags/肺炎疫情.md:
--------------------------------------------------------------------------------
1 | :alarm_clock: 更新时间: 2025-12-13 23:00:43。[来源分类](../README.md)、[标签分类](../TAGS.md)、[时间分类](../TIMELINE.md)
2 |
3 | ## 肺炎疫情
4 |
5 |
6 | > 关键字:`肺炎`、`肺炎疫情`、`武汉肺炎`
7 |
8 |
9 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "scripts": {
3 | "install": "cd server && cnpm install",
4 | "update": "cd server && node once.js",
5 | "auto": "cd server && node app.js"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/details/tags/typescript.md:
--------------------------------------------------------------------------------
1 | :alarm_clock: 更新时间: 2025-12-13 23:00:43。[来源分类](../README.md)、[标签分类](../TAGS.md)、[时间分类](../TIMELINE.md)
2 |
3 | ## TypeScript
4 |
5 |
6 | > 关键字:`TypeScript`
7 |
8 |
9 |
--------------------------------------------------------------------------------
/site/config/dev.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const merge = require('webpack-merge')
3 | const prodEnv = require('./prod.env')
4 |
5 | module.exports = merge(prodEnv, {
6 | NODE_ENV: '"development"'
7 | })
8 |
--------------------------------------------------------------------------------
/details/tags/dev-mobile.md:
--------------------------------------------------------------------------------
1 | :alarm_clock: 更新时间: 2025-12-13 23:00:43。[来源分类](../README.md)、[标签分类](../TAGS.md)、[时间分类](../TIMELINE.md)
2 |
3 | ## 移动开发、Flutter相关
4 |
5 |
6 | > 关键字:`Flutter`、`PWA`、`移动开发`
7 |
8 |
9 |
--------------------------------------------------------------------------------
/site/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/details/tags/dev-game.md:
--------------------------------------------------------------------------------
1 | :alarm_clock: 更新时间: 2025-12-13 23:00:43。[来源分类](../README.md)、[标签分类](../TAGS.md)、[时间分类](../TIMELINE.md)
2 |
3 | ## 游戏开发
4 |
5 |
6 | > 关键字:`游戏`、`Three.js`、`Create.js`、`Matter.js`
7 |
8 |
9 |
--------------------------------------------------------------------------------
/details/tags/server.md:
--------------------------------------------------------------------------------
1 | :alarm_clock: 更新时间: 2025-12-13 23:00:43。[来源分类](../README.md)、[标签分类](../TAGS.md)、[时间分类](../TIMELINE.md)
2 |
3 | ## 服务端相关
4 |
5 |
6 | > 关键字:`Nginx`、`Docker`、`GraphQL`、`REST`、`gRPC`
7 |
8 |
9 |
--------------------------------------------------------------------------------
/details/tags/miniprogram.md:
--------------------------------------------------------------------------------
1 | :alarm_clock: 更新时间: 2025-12-13 23:00:43。[来源分类](../README.md)、[标签分类](../TAGS.md)、[时间分类](../TIMELINE.md)
2 |
3 | ## 小程序
4 |
5 |
6 | > 关键字:`小程序`、`Taro`、`MPVue`、`Wepy`、`Chameleon`
7 |
8 |
9 |
--------------------------------------------------------------------------------
/details/tags/react.md:
--------------------------------------------------------------------------------
1 | :alarm_clock: 更新时间: 2025-12-13 23:00:43。[来源分类](../README.md)、[标签分类](../TAGS.md)、[时间分类](../TIMELINE.md)
2 |
3 | ## React
4 |
5 |
6 | > 关键字:`React`、`Rax`、`Nerv`、`Redux`、`useEffect`、`Hooks`
7 |
8 |
9 |
--------------------------------------------------------------------------------
/details/tags/front-end-advanced.md:
--------------------------------------------------------------------------------
1 | :alarm_clock: 更新时间: 2025-12-13 23:00:43。[来源分类](../README.md)、[标签分类](../TAGS.md)、[时间分类](../TIMELINE.md)
2 |
3 | ## 前端进阶相关
4 |
5 |
6 | > 关键字:`AST`、`GPU`、`WebAssembly`、`Vim`、`HTTP`、`算法`、`全栈`
7 |
8 |
9 |
--------------------------------------------------------------------------------
/site/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules/
3 | /dist/
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 |
8 | # Editor directories and files
9 | .idea
10 | .vscode
11 | *.suo
12 | *.ntvs*
13 | *.njsproj
14 | *.sln
15 |
--------------------------------------------------------------------------------
/details/tags/audio-video.md:
--------------------------------------------------------------------------------
1 | :alarm_clock: 更新时间: 2025-12-13 23:00:43。[来源分类](../README.md)、[标签分类](../TAGS.md)、[时间分类](../TIMELINE.md)
2 |
3 | ## 音视频相关
4 |
5 |
6 | > 关键字:`WebVR`、`WebRTC`、`Video`、`Audio`、`图像`、`音频`、`视频`、`直播`、`摄像头`、`播放器`
7 |
8 |
9 |
--------------------------------------------------------------------------------
/details/tags/canvas-image.md:
--------------------------------------------------------------------------------
1 | :alarm_clock: 更新时间: 2025-12-13 23:00:43。[来源分类](../README.md)、[标签分类](../TAGS.md)、[时间分类](../TIMELINE.md)
2 |
3 | ## Canvas、SVG、图像
4 |
5 |
6 | > 关键字:`Canvas`、`SVG`、`WebGL`、`3D`、`PNG`、`WebP`、`RGB`、`GUI`
7 |
8 |
9 |
--------------------------------------------------------------------------------
/details/tags/optimization.md:
--------------------------------------------------------------------------------
1 | :alarm_clock: 更新时间: 2025-12-13 23:00:43。[来源分类](../README.md)、[标签分类](../TAGS.md)、[时间分类](../TIMELINE.md)
2 |
3 | ## 性能优化
4 |
5 |
6 | > 关键字:`性能`、`优化`、`加载`、`SEO`、`Hints`、`Prefetch`、`Prerender`、`Preload`
7 |
8 |
9 |
--------------------------------------------------------------------------------
/details/tags/nodejs.md:
--------------------------------------------------------------------------------
1 | :alarm_clock: 更新时间: 2025-12-13 23:00:43。[来源分类](../README.md)、[标签分类](../TAGS.md)、[时间分类](../TIMELINE.md)
2 |
3 | ## NodeJS
4 |
5 |
6 | > 关键字:`Node`、`Node.js`、`Express`、`Koa`、`egg.js`、`pandora.js`、`Electron`、`V8`
7 |
8 |
9 |
--------------------------------------------------------------------------------
/details/tags/other.md:
--------------------------------------------------------------------------------
1 | :alarm_clock: 更新时间: 2025-12-13 23:00:43。[来源分类](../README.md)、[标签分类](../TAGS.md)、[时间分类](../TIMELINE.md)
2 |
3 | ## 其它
4 |
5 |
6 |
7 |
8 | - [2025-12-04-单IMG标签的图片内阴影效果实现](https://www.zhangxinxu.com/wordpress/2025/12/img-inset-shadow/)
--------------------------------------------------------------------------------
/now.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 2,
3 | "builds": [
4 | {
5 | "src": "site/package.json",
6 | "use": "@now/static-build"
7 | }
8 | ],
9 | "routes": [
10 | {
11 | "src": "/(.*)",
12 | "dest": "site/$1"
13 | }
14 | ]
15 | }
--------------------------------------------------------------------------------
/site/src/components/notFound.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | 对不起,notFound
4 |
5 |
6 |
7 |
12 |
13 |
16 |
--------------------------------------------------------------------------------
/details/tags/pack-build.md:
--------------------------------------------------------------------------------
1 | :alarm_clock: 更新时间: 2025-12-13 23:00:43。[来源分类](../README.md)、[标签分类](../TAGS.md)、[时间分类](../TIMELINE.md)
2 |
3 | ## Webpack、NPM、构建相关
4 |
5 |
6 | > 关键字:`Webpack`、`Lerna`、`Rollup`、`NPM`、`NPX`、`Yarn`、`Gulp`、`Grunt`、`Babel`、`ESLint`、`TSLint`、`构建`
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .AppleDouble
3 | .LSOverride
4 | .svn
5 |
6 | ._*
7 |
8 | .Spotlight-V100
9 | .Trashes
10 |
11 | Thumbs.db
12 | ehthumbs.db
13 |
14 | Desktop.ini
15 |
16 | $RECYCLE.BIN/
17 |
18 | .idea
19 |
20 | *.sublime-*
21 |
22 | .vscode
23 |
24 | node_modules
25 | *.js.map
26 | package-lock.json
27 | ./email.sh
28 |
--------------------------------------------------------------------------------
/details/tags/browser.md:
--------------------------------------------------------------------------------
1 | :alarm_clock: 更新时间: 2025-12-13 23:00:43。[来源分类](../README.md)、[标签分类](../TAGS.md)、[时间分类](../TIMELINE.md)
2 |
3 | ## 浏览器相关
4 |
5 |
6 | > 关键字:`Chrome`、`Chromium`、`IE`、`Firefox`、`Safari`、`Webkit`、`Edge`、`WebSocket`、`GET`、`POST`、`CORS`、`URL`、`浏览器`、`调试`、`缓存`、`跨域`、`请求`、`安全`、`状态码`、`重绘`、`重排`、`渲染`
7 |
8 |
9 |
10 | - [2025-11-28-醒醒,该使用CookieStore新建和管理cookie了](https://www.zhangxinxu.com/wordpress/2025/11/js-cookiestore-cookie/)
--------------------------------------------------------------------------------
/templates/DETAILS.md:
--------------------------------------------------------------------------------
1 | :alarm_clock: 更新时间: <%= obj.currentDate %>。[来源分类](../README.md)、[标签分类](../TAGS.md)、[时间分类](../TIMELINE.md)
2 |
3 | ## <%= obj.title %>
4 |
5 | <% if(obj.keywords){ %>
6 | > 关键字:`<%= obj.keywords.replace(/(\?)|([:])/g, '').split('|').join('`、`') %>`
7 | <% } %>
8 |
9 | <% _.each(obj.items, function(item){ var itemTitle = obj.formatTitle(item.title); %>
10 | - [<%= item.date %>-<%= itemTitle %>](<%= item.link %>) <% }) %>
--------------------------------------------------------------------------------
/site/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | ["env", {
4 | "modules": false,
5 | "targets": {
6 | "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
7 | }
8 | }],
9 | "stage-2"
10 | ],
11 | "plugins": [
12 | ["import", {
13 | "libraryName": "vant",
14 | "libraryDirectory": "es",
15 | "style": true
16 | }],
17 | "transform-vue-jsx",
18 | "transform-runtime"
19 | ]
20 | }
21 |
--------------------------------------------------------------------------------
/site/.postcssrc.js:
--------------------------------------------------------------------------------
1 | // https://github.com/michael-ciniawsky/postcss-load-config
2 |
3 | module.exports = {
4 | "plugins": {
5 | "postcss-import": {},
6 | "postcss-url": {},
7 | // to edit target browsers: use "browserslist" field in package.json
8 | "autoprefixer": {
9 | browsers: ['Android >= 4.0', 'iOS >= 7']
10 | },
11 | 'postcss-pxtorem': {
12 | rootValue: 16,
13 | propList: ['*']
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/site/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Router from 'vue-router'
3 | import Index from '@/components/Index'
4 | import notFound from '@/components/notFound'
5 | Vue.use(Router)
6 |
7 | export default new Router({
8 | mode: 'history',
9 | routes: [
10 | {
11 | path: '/',
12 | name: 'Index',
13 | component: Index
14 | }, {
15 | path: '/404',
16 | name: 'notFound',
17 | component: notFound
18 | }, {
19 | path: '*',
20 | redirect: '/404'
21 | }
22 | ]
23 | })
24 |
--------------------------------------------------------------------------------
/details/tags/css.md:
--------------------------------------------------------------------------------
1 | :alarm_clock: 更新时间: 2025-12-13 23:00:43。[来源分类](../README.md)、[标签分类](../TAGS.md)、[时间分类](../TIMELINE.md)
2 |
3 | ## CSS
4 |
5 |
6 | > 关键字:`CSS`、`Sass`、`Less`、`scale`、`transform`、`transition`、`animation`、`border`、`background`、`font-weight`、`font-face`、`flex`、`display`、`position`、`居中`、`动画`
7 |
8 |
9 |
10 | - [2025-12-12-CSS-progress函数简介](https://www.zhangxinxu.com/wordpress/2025/12/css-progress-function/)
11 | - [2025-11-24-巧用CSS-::details-content伪元素实现任意展开动画](https://www.zhangxinxu.com/wordpress/2025/11/css-details-target-content-open/)
--------------------------------------------------------------------------------
/site/README.md:
--------------------------------------------------------------------------------
1 | # site
2 |
3 | > A Vue.js project
4 |
5 | ## Build Setup
6 |
7 | ``` bash
8 | # install dependencies
9 | npm install
10 |
11 | # serve with hot reload at localhost:8080
12 | npm run dev
13 |
14 | # build for production with minification
15 | npm run build
16 |
17 | # build for production and view the bundle analyzer report
18 | npm run build --report
19 | ```
20 |
21 | For a detailed explanation on how things work, check out the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader).
22 |
--------------------------------------------------------------------------------
/site/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
15 |
16 |
28 |
--------------------------------------------------------------------------------
/details/tags/javascript.md:
--------------------------------------------------------------------------------
1 | :alarm_clock: 更新时间: 2025-12-13 23:00:43。[来源分类](../README.md)、[标签分类](../TAGS.md)、[时间分类](../TIMELINE.md)
2 |
3 | ## JavaScript
4 |
5 |
6 | > 关键字:`JavaScript`、`ECMAScript`、`JS`、`ES6`、`Promise`、`document`、`await`、`async`、`decorator`、`module`、`import`、`catch`、`console`、`setInterval`、`Worker`、`fetch`、`this`、`bind`、`DataTransfer`、`ArrayBuffer`、`Component`、`DOM`、`H5`、`HTML5`、`组件`、`正则`、`数组`、`事件`、`深拷贝`、`数据代理`、`变量`、`函数式`、`声明式`、`异步`、`表单`、`滚动`、`scroll`、`防抖`、`适配`、`路由`、`模块化`
7 |
8 |
9 |
10 | - [2025-11-17-介绍下与CSS自定义组件相关的:state函数](https://www.zhangxinxu.com/wordpress/2025/11/css-state-function/)
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: rss
2 |
3 | on:
4 | schedule:
5 | - cron: "0 23 * * *"
6 | jobs:
7 | front-rss-bot:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - name: Checkout
11 | uses: actions/checkout@v2
12 | - name: Set up Node
13 | uses: actions/setup-node@v1
14 | with:
15 | node-version: 10.x
16 | - name: configure
17 | run: |
18 | git config --global user.name "w4ctech"
19 | git config --global user.email "w3ctech@qq.com"
20 | - name: working
21 | run: cd server && npm install && node once.js
22 |
--------------------------------------------------------------------------------
/site/build/vue-loader.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const utils = require('./utils')
3 | const config = require('../config')
4 | const isProduction = process.env.NODE_ENV === 'production'
5 | const sourceMapEnabled = isProduction
6 | ? config.build.productionSourceMap
7 | : config.dev.cssSourceMap
8 |
9 | module.exports = {
10 | loaders: utils.cssLoaders({
11 | sourceMap: sourceMapEnabled,
12 | extract: isProduction
13 | }),
14 | cssSourceMap: sourceMapEnabled,
15 | cacheBusting: config.dev.cacheBusting,
16 | transformToRequire: {
17 | video: ['src', 'poster'],
18 | source: 'src',
19 | img: 'src',
20 | image: 'xlink:href'
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/details/张鑫旭-鑫空间-鑫生活.md:
--------------------------------------------------------------------------------
1 | :alarm_clock: 更新时间: 2025-12-13 23:00:43。[来源分类](../README.md)、[标签分类](../TAGS.md)、[时间分类](../TIMELINE.md)
2 |
3 | ## 张鑫旭-鑫空间-鑫生活
4 |
5 |
6 |
7 |
8 | - [2025-12-12-CSS-progress函数简介](https://www.zhangxinxu.com/wordpress/2025/12/css-progress-function/)
9 | - [2025-12-04-单IMG标签的图片内阴影效果实现](https://www.zhangxinxu.com/wordpress/2025/12/img-inset-shadow/)
10 | - [2025-11-28-醒醒,该使用CookieStore新建和管理cookie了](https://www.zhangxinxu.com/wordpress/2025/11/js-cookiestore-cookie/)
11 | - [2025-11-24-巧用CSS-::details-content伪元素实现任意展开动画](https://www.zhangxinxu.com/wordpress/2025/11/css-details-target-content-open/)
12 | - [2025-11-17-介绍下与CSS自定义组件相关的:state函数](https://www.zhangxinxu.com/wordpress/2025/11/css-state-function/)
--------------------------------------------------------------------------------
/templates/TAGS.md:
--------------------------------------------------------------------------------
1 | > 提示:只是根据标题文案简单匹配分类
2 |
3 | :alarm_clock: 更新时间: <%= obj.currentDate %>。[来源分类](./README.md)、[时间分类](./TIMELINE.md)
4 |
5 | ## 标签分类
6 | <% _.each(obj.tags, function(e){ %>
7 | - [<%= e.tag %>](#<%= e.tag.toLowerCase() %>) <% }) %>
8 |
9 | ## 文章链接
10 | <% _.each(obj.tags, function(e){ %>
11 |
12 |
13 | <%= e.tag %>
14 |
15 |
16 |
17 | <% if(e.keywords){ %>
18 | > 关键字:`<%= e.keywords.replace(/(\?)|([:])/g, '').split('|').join('`、`') %>`
19 | <% } %>
20 |
21 | <% _.each(e.items.slice(0,20), function(item){ var itemTitle = obj.formatTitle(item.title); %>
22 | - [【<%= item.rssTitle %>】<%= itemTitle %>](<%= item.link %>)<% }) %>
23 | - [......【查看更多】......](./details/tags/<%= e.filename %>.md)
24 |
25 |
26 |
27 | <% }) %>
28 |
--------------------------------------------------------------------------------
/site/src/main.js:
--------------------------------------------------------------------------------
1 | // The Vue build version to load with the `import` command
2 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias.
3 | import Vue from 'vue'
4 | import '@vant/touch-emulator'
5 | import { Search, Icon, Popup, Cell, CellGroup, Tag, Divider, Skeleton } from 'vant'
6 | import infiniteScroll from 'vue-infinite-scroll'
7 | import App from './App'
8 | import router from './router'
9 | import moment from 'moment'
10 | import axios from "axios"
11 | Vue.prototype.bus = new Vue()
12 | Vue.config.productionTip = false
13 | Vue.prototype.$moment = moment
14 | Vue.prototype.$axios = axios
15 | Vue.use(infiniteScroll).use(Search).use(Icon).use(Popup).use(Cell).use(CellGroup).use(Tag).use(Divider).use(Skeleton)
16 |
17 | /* eslint-disable no-new */
18 | new Vue({
19 | el: '#app',
20 | router,
21 | components: { App },
22 | template: ''
23 | })
24 |
25 |
--------------------------------------------------------------------------------
/site/.eslintrc.js:
--------------------------------------------------------------------------------
1 | // https://eslint.org/docs/user-guide/configuring
2 |
3 | module.exports = {
4 | root: true,
5 | parserOptions: {
6 | parser: 'babel-eslint'
7 | },
8 | env: {
9 | browser: true,
10 | },
11 | extends: [
12 | // https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
13 | // consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules.
14 | 'plugin:vue/essential',
15 | // https://github.com/standard/standard/blob/master/docs/RULES-en.md
16 | 'standard'
17 | ],
18 | // required to lint *.vue files
19 | plugins: [
20 | 'vue'
21 | ],
22 | // add your custom rules here
23 | rules: {
24 | // allow async-await
25 | 'generator-star-spacing': 'off',
26 | // allow debugger during development
27 | 'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/templates/TIMELINE.md:
--------------------------------------------------------------------------------
1 | :alarm_clock: 更新时间: <%= obj.currentDate %>。[来源分类](./README.md)、[标签分类](./TAGS.md)
2 |
3 | ## 时间分类
4 |
5 |
6 | <% _.each(obj.dataYears, function(year){ %>
7 |
8 | | <%= year %>年 |
9 |
10 | <% _.each((new Array(12)), function(e, idx){ idx++; idx = idx < 10 ? ('0' + idx) : idx; var date = year + '-' + idx; %>
11 | | <% if(obj.dataKeys.indexOf(date) > -1) { %><%= idx %>月<% } else { %><%= idx %>月<% } %> | <% }) %>
12 |
13 | <% }) %>
14 |
15 |
16 | ## 文章链接
17 | <% _.each(obj.dataKeys, function(e){ %>
18 |
19 |
20 | <%= e %>
21 |
22 |
23 | <% _.each(obj.dataObj[e], function(item){ var itemTitle = obj.formatTitle(item.title); %>
24 | - [【<%= item.rssTitle %>】<%= item.date %>-<%= itemTitle %>](<%= item.link %>) <% }) %>
25 |
26 |
27 |
28 | <% }) %>
29 |
--------------------------------------------------------------------------------
/server/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "front-end-rss",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "dependencies": {
6 | "async": "^2.6.1",
7 | "axios": "^0.19.1",
8 | "clone-deep": "^4.0.0",
9 | "later": "^1.2.0",
10 | "moment": "^2.22.2",
11 | "query-string": "^6.8.1",
12 | "rimraf": "^3.0.0",
13 | "rss-parser": "^3.4.3",
14 | "simple-git": "^1.102.0",
15 | "underscore": "^1.12.1"
16 | },
17 | "description": "front-end-rss",
18 | "devDependencies": {},
19 | "scripts": {
20 | "test": "echo \"Error: no test specified\" && exit 1",
21 | "update": "node once.js"
22 | },
23 | "author": "w4ctech",
24 | "license": "MIT",
25 | "repository": {
26 | "type": "git",
27 | "url": "git://github.com/w4ctech/front-end-rss.git"
28 | },
29 | "bugs": {
30 | "url": "https://github.com/w4ctech/front-end-rss/issues"
31 | },
32 | "homepage": "https://github.com/w4ctech/front-end-rss#readme"
33 | }
34 |
--------------------------------------------------------------------------------
/site/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | w4ctech—深自缄默 如云漂泊
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
29 |
30 |
--------------------------------------------------------------------------------
/site/build/build.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | require('./check-versions')()
3 |
4 | process.env.NODE_ENV = 'production'
5 |
6 | const ora = require('ora')
7 | const rm = require('rimraf')
8 | const path = require('path')
9 | const chalk = require('chalk')
10 | const webpack = require('webpack')
11 | const config = require('../config')
12 | const webpackConfig = require('./webpack.prod.conf')
13 |
14 | const spinner = ora('building for production...')
15 | spinner.start()
16 |
17 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
18 | if (err) throw err
19 | webpack(webpackConfig, (err, stats) => {
20 | spinner.stop()
21 | if (err) throw err
22 | process.stdout.write(stats.toString({
23 | colors: true,
24 | modules: false,
25 | children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
26 | chunks: false,
27 | chunkModules: false
28 | }) + '\n\n')
29 |
30 | if (stats.hasErrors()) {
31 | console.log(chalk.red(' Build failed with errors.\n'))
32 | process.exit(1)
33 | }
34 |
35 | console.log(chalk.cyan(' Build complete.\n'))
36 | console.log(chalk.yellow(
37 | ' Tip: built files are meant to be served over an HTTP server.\n' +
38 | ' Opening index.html over file:// won\'t work.\n'
39 | ))
40 | })
41 | })
42 |
--------------------------------------------------------------------------------
/TIMELINE.md:
--------------------------------------------------------------------------------
1 | :alarm_clock: 更新时间: 2025-12-13 23:00:43。[来源分类](./README.md)、[标签分类](./TAGS.md)
2 |
3 | ## 时间分类
4 |
5 |
6 |
7 |
8 | | 2025年 |
9 |
10 |
11 | | 01月 |
12 | 02月 |
13 | 03月 |
14 | 04月 |
15 | 05月 |
16 | 06月 |
17 | 07月 |
18 | 08月 |
19 | 09月 |
20 | 10月 |
21 | 11月 |
22 | 12月 |
23 |
24 |
25 |
26 |
27 | ## 文章链接
28 |
29 |
30 |
31 | 2025-12
32 |
33 |
34 |
35 | - [【张鑫旭-鑫空间-鑫生活】2025-12-12-CSS-progress函数简介](https://www.zhangxinxu.com/wordpress/2025/12/css-progress-function/)
36 | - [【张鑫旭-鑫空间-鑫生活】2025-12-04-单IMG标签的图片内阴影效果实现](https://www.zhangxinxu.com/wordpress/2025/12/img-inset-shadow/)
37 |
38 |
39 |
40 |
41 |
42 |
43 | 2025-11
44 |
45 |
46 |
47 | - [【张鑫旭-鑫空间-鑫生活】2025-11-28-醒醒,该使用CookieStore新建和管理cookie了](https://www.zhangxinxu.com/wordpress/2025/11/js-cookiestore-cookie/)
48 | - [【张鑫旭-鑫空间-鑫生活】2025-11-24-巧用CSS-::details-content伪元素实现任意展开动画](https://www.zhangxinxu.com/wordpress/2025/11/css-details-target-content-open/)
49 | - [【张鑫旭-鑫空间-鑫生活】2025-11-17-介绍下与CSS自定义组件相关的:state函数](https://www.zhangxinxu.com/wordpress/2025/11/css-state-function/)
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/templates/README.md:
--------------------------------------------------------------------------------
1 |
4 |
5 | ##
6 |
7 | - 项目目的:每天定时抓取最新前端技术文章,并推送到 GitHub 方便查看
8 | - 文章来源:RSS 订阅源
9 | - 定时抓取:每30分钟一次
10 | - 文章分类:[标签分类](./TAGS.md)、[时间分类](./TIMELINE.md)
11 |
12 | ##
13 |
14 | :alarm_clock: 更新时间: <%= obj.currentDate %>,:rocket: 更新条数: +<%= obj.newData.length %>,  表示有更新
15 |
16 | ## 来源分类
17 | <% _.each(obj.linksJson, function(e){ var rssTitle = obj.formatTitle(e.title); %>
18 | - [<%= rssTitle %>](#<%= rssTitle.toLowerCase() %>)<% if (e.rss in obj.newData.rss){ %> <% } %> <% }) %>
19 |
20 | ## 文章链接
21 | <% _.each(obj.linksJson, function(e){ var rssTitle = obj.formatTitle(e.title); %>
22 |
23 |
26 |
27 | <% _.each(e.items.slice(0,20), function(item, index){ var itemTitle = obj.formatTitle(item.title); %>
28 | - [<%= item.date %>-<%= itemTitle %>](<%= item.link %>) <% if (e.rss in obj.newData.rss && item.link in obj.newData.links){ %> <% } %> <% }) %>
29 | - [......【查看更多】......](./details/<%= e.title %>.md)
30 |
31 |
32 |
33 | <% }) %>
34 |
35 | ## 其它
36 | 感谢 [RSSHub](https://github.com/DIYgod/RSSHub) 提供的微信公众号 RSS 链接 Fork自 [ChanceYu](https://github.com/ChanceYu/front-end-rss)
37 |
--------------------------------------------------------------------------------
/site/build/check-versions.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const chalk = require('chalk')
3 | const semver = require('semver')
4 | const packageConfig = require('../package.json')
5 | const shell = require('shelljs')
6 |
7 | function exec (cmd) {
8 | return require('child_process').execSync(cmd).toString().trim()
9 | }
10 |
11 | const versionRequirements = [
12 | {
13 | name: 'node',
14 | currentVersion: semver.clean(process.version),
15 | versionRequirement: packageConfig.engines.node
16 | }
17 | ]
18 |
19 | if (shell.which('npm')) {
20 | versionRequirements.push({
21 | name: 'npm',
22 | currentVersion: exec('npm --version'),
23 | versionRequirement: packageConfig.engines.npm
24 | })
25 | }
26 |
27 | module.exports = function () {
28 | const warnings = []
29 |
30 | for (let i = 0; i < versionRequirements.length; i++) {
31 | const mod = versionRequirements[i]
32 |
33 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
34 | warnings.push(mod.name + ': ' +
35 | chalk.red(mod.currentVersion) + ' should be ' +
36 | chalk.green(mod.versionRequirement)
37 | )
38 | }
39 | }
40 |
41 | if (warnings.length) {
42 | console.log('')
43 | console.log(chalk.yellow('To use this template, you must update following to modules:'))
44 | console.log()
45 |
46 | for (let i = 0; i < warnings.length; i++) {
47 | const warning = warnings[i]
48 | console.log(' ' + warning)
49 | }
50 |
51 | console.log()
52 | process.exit(1)
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/server/app.js:
--------------------------------------------------------------------------------
1 | const later = require('later')
2 |
3 | const handlerUpdate = require('./update')
4 |
5 | // node app.js 设置自动更新
6 | later.date.localTime()
7 | later.setInterval(handlerUpdate, {
8 | schedules: [
9 | { h: [00], m: [00] },
10 | { h: [00], m: [30] },
11 | { h: [01], m: [00] },
12 | { h: [01], m: [30] },
13 | { h: [02], m: [00] },
14 | { h: [02], m: [30] },
15 | { h: [03], m: [00] },
16 | { h: [03], m: [30] },
17 | { h: [04], m: [00] },
18 | { h: [04], m: [30] },
19 | { h: [05], m: [00] },
20 | { h: [05], m: [30] },
21 | { h: [06], m: [00] },
22 | { h: [06], m: [30] },
23 | { h: [07], m: [00] },
24 | { h: [07], m: [30] },
25 | { h: [08], m: [00] },
26 | { h: [08], m: [30] },
27 | { h: [09], m: [00] },
28 | { h: [09], m: [30] },
29 | { h: [10], m: [00] },
30 | { h: [10], m: [30] },
31 | { h: [11], m: [00] },
32 | { h: [11], m: [30] },
33 | { h: [12], m: [00] },
34 | { h: [12], m: [30] },
35 | { h: [13], m: [00] },
36 | { h: [13], m: [30] },
37 | { h: [14], m: [00] },
38 | { h: [14], m: [30] },
39 | { h: [15], m: [00] },
40 | { h: [15], m: [30] },
41 | { h: [16], m: [00] },
42 | { h: [16], m: [30] },
43 | { h: [17], m: [00] },
44 | { h: [17], m: [30] },
45 | { h: [18], m: [00] },
46 | { h: [18], m: [30] },
47 | { h: [19], m: [00] },
48 | { h: [19], m: [30] },
49 | { h: [20], m: [00] },
50 | { h: [20], m: [30] },
51 | { h: [21], m: [00] },
52 | { h: [21], m: [30] },
53 | { h: [22], m: [00] },
54 | { h: [22], m: [30] },
55 | { h: [23], m: [00] },
56 | { h: [23], m: [30] }
57 | ]
58 | })
59 |
--------------------------------------------------------------------------------
/server/utils.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs')
2 | const path = require('path')
3 | const moment = require('moment')
4 |
5 | const RESP_ROOT = '../';
6 | const RESP_PATH = path.join(RESP_ROOT)
7 | const RSS_PATH = path.join(RESP_ROOT + '/data/rss.json')
8 | const LINKS_PATH = path.join(RESP_ROOT + '/data/links.json')
9 | const TAGS_PATH = path.join(RESP_ROOT + '/data/tags.json')
10 | const README_PATH = path.join(RESP_ROOT + '/README.md')
11 | const README_TEMPLATE_PATH = path.join(RESP_ROOT + '/templates/README.md')
12 | const TAGS_MD_PATH = path.join(RESP_ROOT + '/TAGS.md')
13 | const TAGS_TEMPLATE_PATH = path.join(RESP_ROOT + '/templates/TAGS.md')
14 | const TIMELINE_MD_PATH = path.join(RESP_ROOT + '/TIMELINE.md')
15 | const TIMELINE_TEMPLATE_PATH = path.join(RESP_ROOT + '/templates/TIMELINE.md')
16 | const DETAILS_TEMPLATE_PATH = path.join(RESP_ROOT + '/templates/DETAILS.md')
17 |
18 | module.exports = {
19 | /**
20 | * 文件路径
21 | */
22 | PATH: {
23 | RESP_PATH,
24 | RSS_PATH,
25 | LINKS_PATH,
26 | TAGS_PATH,
27 | README_PATH,
28 | README_TEMPLATE_PATH,
29 | TAGS_MD_PATH,
30 | TAGS_TEMPLATE_PATH,
31 | TIMELINE_MD_PATH,
32 | TIMELINE_TEMPLATE_PATH,
33 | DETAILS_TEMPLATE_PATH,
34 | },
35 |
36 | /**
37 | * 格式化标题
38 | */
39 | formatTitle: function(title, isRsshub){
40 | // https://front-rss.herokuapp.com
41 | if(isRsshub){
42 | let matches = title.match(/“(.*)”/)
43 |
44 | if(matches && matches[1]){
45 | title = matches[1]
46 | }
47 | }
48 | return title.replace('', '').replace(/[\[\]\(\)]/g, '').replace(/\s+/g, '-')
49 | },
50 |
51 | /**
52 | * 格式化时间
53 | */
54 | getNowDate: function(){
55 | return moment().format('YYYY-MM-DD HH:mm:ss')
56 | },
57 |
58 | /**
59 | * 获取 links.json 数据
60 | */
61 | getLinksJson: function(){
62 | return JSON.parse(fs.readFileSync(LINKS_PATH).toString())
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/site/config/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | // Template version: 1.3.1
3 | // see http://vuejs-templates.github.io/webpack for documentation.
4 |
5 | const path = require('path')
6 |
7 | module.exports = {
8 | dev: {
9 |
10 | // Paths
11 | assetsSubDirectory: 'static',
12 | assetsPublicPath: '/',
13 | proxyTable: {},
14 |
15 | // Various Dev Server settings
16 | host: 'localhost', // can be overwritten by process.env.HOST
17 | port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
18 | autoOpenBrowser: false,
19 | errorOverlay: true,
20 | notifyOnErrors: true,
21 | poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
22 |
23 | // Use Eslint Loader?
24 | // If true, your code will be linted during bundling and
25 | // linting errors and warnings will be shown in the console.
26 | useEslint: true,
27 | // If true, eslint errors and warnings will also be shown in the error overlay
28 | // in the browser.
29 | showEslintErrorsInOverlay: false,
30 |
31 | /**
32 | * Source Maps
33 | */
34 |
35 | // https://webpack.js.org/configuration/devtool/#development
36 | devtool: 'cheap-module-eval-source-map',
37 |
38 | // If you have problems debugging vue-files in devtools,
39 | // set this to false - it *may* help
40 | // https://vue-loader.vuejs.org/en/options.html#cachebusting
41 | cacheBusting: true,
42 |
43 | cssSourceMap: true
44 | },
45 |
46 | build: {
47 | // Template for index.html
48 | index: path.resolve(__dirname, '../dist/index.html'),
49 |
50 | // Paths
51 | assetsRoot: path.resolve(__dirname, '../dist'),
52 | assetsSubDirectory: 'static',
53 | assetsPublicPath: '/',
54 |
55 | /**
56 | * Source Maps
57 | */
58 |
59 | productionSourceMap: true,
60 | // https://webpack.js.org/configuration/devtool/#production
61 | devtool: '#source-map',
62 |
63 | // Gzip off by default as many popular static hosts such as
64 | // Surge or Netlify already gzip all static assets for you.
65 | // Before setting to `true`, make sure to:
66 | // npm install --save-dev compression-webpack-plugin
67 | productionGzip: false,
68 | productionGzipExtensions: ['js', 'css'],
69 |
70 | // Run the build command with an extra argument to
71 | // View the bundle analyzer report after build finishes:
72 | // `npm run build --report`
73 | // Set to `true` or `false` to always turn it on or off
74 | bundleAnalyzerReport: process.env.npm_config_report
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/site/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "site",
3 | "version": "1.0.0",
4 | "description": "A Vue.js project",
5 | "author": "w4ctech ",
6 | "private": true,
7 | "scripts": {
8 | "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
9 | "start": "npm run dev",
10 | "lint": "eslint --ext .js,.vue src",
11 | "build": "node build/build.js"
12 | },
13 | "dependencies": {
14 | "@vant/touch-emulator": "^1.1.0",
15 | "axios": "^0.19.1",
16 | "dayjs": "^1.8.16",
17 | "moment": "^2.24.0",
18 | "vant": "^2.2.9",
19 | "vue": "^2.5.2",
20 | "vue-infinite-scroll": "^2.0.2",
21 | "vue-router": "^3.0.1"
22 | },
23 | "devDependencies": {
24 | "autoprefixer": "^7.1.2",
25 | "babel-core": "^6.22.1",
26 | "babel-eslint": "^8.2.1",
27 | "babel-helper-vue-jsx-merge-props": "^2.0.3",
28 | "babel-loader": "^7.1.1",
29 | "babel-plugin-import": "^1.12.2",
30 | "babel-plugin-syntax-jsx": "^6.18.0",
31 | "babel-plugin-transform-runtime": "^6.22.0",
32 | "babel-plugin-transform-vue-jsx": "^3.5.0",
33 | "babel-preset-env": "^1.3.2",
34 | "babel-preset-stage-2": "^6.22.0",
35 | "chalk": "^2.0.1",
36 | "copy-webpack-plugin": "^4.0.1",
37 | "css-loader": "^0.28.0",
38 | "eslint": "^4.15.0",
39 | "eslint-config-standard": "^10.2.1",
40 | "eslint-friendly-formatter": "^3.0.0",
41 | "eslint-loader": "^1.7.1",
42 | "eslint-plugin-import": "^2.7.0",
43 | "eslint-plugin-node": "^5.2.0",
44 | "eslint-plugin-promise": "^3.4.0",
45 | "eslint-plugin-standard": "^3.0.1",
46 | "eslint-plugin-vue": "^4.0.0",
47 | "extract-text-webpack-plugin": "^3.0.0",
48 | "file-loader": "^1.1.4",
49 | "friendly-errors-webpack-plugin": "^1.6.1",
50 | "html-webpack-plugin": "^2.30.1",
51 | "node-notifier": "^5.1.2",
52 | "optimize-css-assets-webpack-plugin": "^3.2.0",
53 | "ora": "^1.2.0",
54 | "portfinder": "^1.0.13",
55 | "postcss-import": "^11.0.0",
56 | "postcss-loader": "^2.0.8",
57 | "postcss-pxtorem": "^4.0.1",
58 | "postcss-url": "^7.2.1",
59 | "rimraf": "^2.6.0",
60 | "semver": "^5.3.0",
61 | "shelljs": "^0.7.6",
62 | "uglifyjs-webpack-plugin": "^1.1.1",
63 | "url-loader": "^0.5.8",
64 | "vue-loader": "^13.3.0",
65 | "vue-style-loader": "^3.0.1",
66 | "vue-template-compiler": "^2.5.2",
67 | "webpack": "^3.6.0",
68 | "webpack-bundle-analyzer": "^2.9.0",
69 | "webpack-dev-server": "^2.9.1",
70 | "webpack-merge": "^4.1.0"
71 | },
72 | "engines": {
73 | "node": ">= 6.0.0",
74 | "npm": ">= 3.0.0"
75 | },
76 | "browserslist": [
77 | "> 1%",
78 | "last 2 versions",
79 | "not ie <= 8"
80 | ]
81 | }
--------------------------------------------------------------------------------
/site/build/webpack.base.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const utils = require('./utils')
4 | const config = require('../config')
5 | const vueLoaderConfig = require('./vue-loader.conf')
6 |
7 | function resolve (dir) {
8 | return path.join(__dirname, '..', dir)
9 | }
10 |
11 | const createLintingRule = () => ({
12 | test: /\.(js|vue)$/,
13 | loader: 'eslint-loader',
14 | enforce: 'pre',
15 | include: [resolve('src'), resolve('test')],
16 | options: {
17 | formatter: require('eslint-friendly-formatter'),
18 | emitWarning: !config.dev.showEslintErrorsInOverlay
19 | }
20 | })
21 |
22 | module.exports = {
23 | context: path.resolve(__dirname, '../'),
24 | entry: {
25 | app: './src/main.js'
26 | },
27 | output: {
28 | path: config.build.assetsRoot,
29 | filename: '[name].js',
30 | publicPath: process.env.NODE_ENV === 'production'
31 | ? config.build.assetsPublicPath
32 | : config.dev.assetsPublicPath
33 | },
34 | resolve: {
35 | extensions: ['.js', '.vue', '.json'],
36 | alias: {
37 | 'vue$': 'vue/dist/vue.esm.js',
38 | '@': resolve('src'),
39 | }
40 | },
41 | module: {
42 | rules: [
43 | // ...(config.dev.useEslint ? [createLintingRule()] : []),
44 | {
45 | test: /\.vue$/,
46 | loader: 'vue-loader',
47 | options: vueLoaderConfig
48 | },
49 | {
50 | test: /\.js$/,
51 | loader: 'babel-loader',
52 | include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
53 | },
54 | {
55 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
56 | loader: 'url-loader',
57 | options: {
58 | limit: 10000,
59 | name: utils.assetsPath('img/[name].[hash:7].[ext]')
60 | }
61 | },
62 | {
63 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
64 | loader: 'url-loader',
65 | options: {
66 | limit: 10000,
67 | name: utils.assetsPath('media/[name].[hash:7].[ext]')
68 | }
69 | },
70 | {
71 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
72 | loader: 'url-loader',
73 | options: {
74 | limit: 10000,
75 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
76 | }
77 | }
78 | ]
79 | },
80 | node: {
81 | // prevent webpack from injecting useless setImmediate polyfill because Vue
82 | // source contains it (although only uses it if it's native).
83 | setImmediate: false,
84 | // prevent webpack from injecting mocks to Node native modules
85 | // that does not make sense for the client
86 | dgram: 'empty',
87 | fs: 'empty',
88 | net: 'empty',
89 | tls: 'empty',
90 | child_process: 'empty'
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/server/update.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs')
2 | const path = require('path')
3 | const async = require('async')
4 | const moment = require('moment')
5 | const Parser = require('rss-parser')
6 | const Git = require('simple-git')
7 | const _ = require('underscore')
8 | const cloneDeep = require('clone-deep')
9 | const rimraf = require('rimraf')
10 | const utils = require('./utils')
11 | const writemd = require('./writemd')
12 | const fetch = require('./fetch')
13 |
14 | const {
15 | RESP_PATH,
16 | RSS_PATH,
17 | LINKS_PATH,
18 | TAGS_PATH,
19 | README_PATH,
20 | README_TEMPLATE_PATH,
21 | TAGS_MD_PATH,
22 | TAGS_TEMPLATE_PATH,
23 | TIMELINE_MD_PATH,
24 | TIMELINE_TEMPLATE_PATH,
25 | } = utils.PATH
26 |
27 | let rssJson = []
28 | let linksJson = []
29 |
30 | // 本次更新的 rss 和链接数据
31 | let newData = {
32 | length: 0,
33 | titles: [],
34 | rss: {},
35 | links: {}
36 | }
37 |
38 | /**
39 | * 更新 git 仓库
40 | */
41 | function handlerUpdate(){
42 | fs.copyFile('./links.json','../data/links.json',function(err){
43 | if(err){
44 | console.log('something wrong was happened')
45 | }
46 | else{
47 | console.log('copy file succeed');
48 | }
49 | })
50 | rimraf('../details/*',function (msg) {
51 | console.log('删除了details目录'+msg)
52 | fs.mkdir('../details/tags',res=>{
53 | if (res) {
54 | return console.error(res);
55 | }
56 | console.log("details/tags目录创建成功。");
57 | })
58 | })
59 | console.log(utils.getNowDate() + ' - 开始更新抓取');
60 | Git(RESP_PATH)
61 | .pull()
62 | .exec(handlerFeed);
63 | }
64 |
65 | /**
66 | * 提交修改到 git 仓库
67 | */
68 | function handlerCommit(){
69 | console.log(utils.getNowDate() + ' - 完成抓取,即将上传');
70 | Git(RESP_PATH)
71 | .add('./*')
72 | .commit('更新: ' + newData.titles.join('、'))
73 | .push(['-u', 'origin', 'master'], () => console.log('完成抓取和上传!','更新了'+newData.titles.join('、')));
74 | }
75 |
76 | /**
77 | * 处理订阅源
78 | */
79 | function handlerFeed(){
80 | rssJson = require(RSS_PATH)
81 | linksJson = require(LINKS_PATH)
82 |
83 | newData = {
84 | length: 0,
85 | titles: [],
86 | rss: {},
87 | links: {}
88 | }
89 |
90 | let parallels = []
91 |
92 | rssJson.forEach((item, index) => {
93 | let jsonItem = linksJson[index] || {}
94 |
95 | parallels.push(function(cb){
96 | fetch(newData, linksJson, index, jsonItem, item, cb);
97 | })
98 | })
99 |
100 | async.parallel(parallels, (err, result) => {
101 | if(newData.length){
102 | fs.writeFileSync(LINKS_PATH, JSON.stringify(result, null, 2), 'utf-8')
103 | writemd(newData)
104 | handlerCommit()
105 | }else{
106 | console.log(utils.getNowDate() + ' - 无需更新');
107 | }
108 | })
109 | }
110 |
111 | module.exports = handlerUpdate
112 |
--------------------------------------------------------------------------------
/site/build/utils.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const config = require('../config')
4 | const ExtractTextPlugin = require('extract-text-webpack-plugin')
5 | const packageConfig = require('../package.json')
6 |
7 | exports.assetsPath = function (_path) {
8 | const assetsSubDirectory = process.env.NODE_ENV === 'production'
9 | ? config.build.assetsSubDirectory
10 | : config.dev.assetsSubDirectory
11 |
12 | return path.posix.join(assetsSubDirectory, _path)
13 | }
14 |
15 | exports.cssLoaders = function (options) {
16 | options = options || {}
17 |
18 | const cssLoader = {
19 | loader: 'css-loader',
20 | options: {
21 | sourceMap: options.sourceMap
22 | }
23 | }
24 |
25 | const postcssLoader = {
26 | loader: 'postcss-loader',
27 | options: {
28 | sourceMap: options.sourceMap
29 | }
30 | }
31 |
32 | // generate loader string to be used with extract text plugin
33 | function generateLoaders (loader, loaderOptions) {
34 | const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
35 |
36 | if (loader) {
37 | loaders.push({
38 | loader: loader + '-loader',
39 | options: Object.assign({}, loaderOptions, {
40 | sourceMap: options.sourceMap
41 | })
42 | })
43 | }
44 |
45 | // Extract CSS when that option is specified
46 | // (which is the case during production build)
47 | if (options.extract) {
48 | return ExtractTextPlugin.extract({
49 | use: loaders,
50 | fallback: 'vue-style-loader'
51 | })
52 | } else {
53 | return ['vue-style-loader'].concat(loaders)
54 | }
55 | }
56 |
57 | // https://vue-loader.vuejs.org/en/configurations/extract-css.html
58 | return {
59 | css: generateLoaders(),
60 | postcss: generateLoaders(),
61 | less: generateLoaders('less'),
62 | sass: generateLoaders('sass', { indentedSyntax: true }),
63 | scss: generateLoaders('sass'),
64 | stylus: generateLoaders('stylus'),
65 | styl: generateLoaders('stylus')
66 | }
67 | }
68 |
69 | // Generate loaders for standalone style files (outside of .vue)
70 | exports.styleLoaders = function (options) {
71 | const output = []
72 | const loaders = exports.cssLoaders(options)
73 |
74 | for (const extension in loaders) {
75 | const loader = loaders[extension]
76 | output.push({
77 | test: new RegExp('\\.' + extension + '$'),
78 | use: loader
79 | })
80 | }
81 |
82 | return output
83 | }
84 |
85 | exports.createNotifierCallback = () => {
86 | const notifier = require('node-notifier')
87 |
88 | return (severity, errors) => {
89 | if (severity !== 'error') return
90 |
91 | const error = errors[0]
92 | const filename = error.file && error.file.split('!').pop()
93 |
94 | notifier.notify({
95 | title: packageConfig.name,
96 | message: severity + ': ' + error.name,
97 | subtitle: filename || '',
98 | icon: path.join(__dirname, 'logo.png')
99 | })
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/data/tags.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "tag": "React",
4 | "filename": "react",
5 | "keywords": "React|Rax|Nerv|Redux|useEffect|Hooks?"
6 | },
7 | {
8 | "tag": "Vue",
9 | "filename": "vue",
10 | "keywords": "Vue|ElementUI"
11 | },
12 | {
13 | "tag": "TypeScript",
14 | "filename": "typescript",
15 | "keywords": "TypeScript"
16 | },
17 | {
18 | "tag": "Webpack、NPM、构建相关",
19 | "filename": "pack-build",
20 | "keywords": "Webpack|Lerna|Rollup|NPM|NPX|Yarn|Gulp|Grunt|Babel|ESLint|TSLint|构建"
21 | },
22 | {
23 | "tag": "NodeJS",
24 | "filename": "nodejs",
25 | "keywords": "Node|Node.?js|Express|Koa|egg.?js|pandora.?js|Electron|V8"
26 | },
27 | {
28 | "tag": "小程序",
29 | "filename": "miniprogram",
30 | "keywords": "小程序|Taro|MPVue|Wepy|Chameleon"
31 | },
32 | {
33 | "tag": "移动开发、Flutter相关",
34 | "filename": "dev-mobile",
35 | "keywords": "Flutter|PWA|移动开发"
36 | },
37 | {
38 | "tag": "游戏开发",
39 | "filename": "dev-game",
40 | "keywords": "游戏|Three.?js|Create.?js|Matter.?js"
41 | },
42 | {
43 | "tag": "JavaScript",
44 | "filename": "javascript",
45 | "keywords": "JavaScript|ECMAScript|JS|ES6|Promise|document|await|async|decorator|module|import|catch|console|setInterval|Worker|fetch|this|bind|DataTransfer|ArrayBuffer|Component|DOM|H5|HTML5|组件|正则|数组|事件|深拷贝|数据代理|变量|函数式|声明式|异步|表单|滚动|scroll|防抖|适配|路由|模块化"
46 | },
47 | {
48 | "tag": "CSS",
49 | "filename": "css",
50 | "keywords": "CSS|Sass|Less|scale|transform|transition|animation|border|background|font-weight|font-face|flex|display|position|居中|动画"
51 | },
52 | {
53 | "tag": "Canvas、SVG、图像",
54 | "filename": "canvas-image",
55 | "keywords": "Canvas|SVG|WebGL|3D|PNG|WebP|RGB|GUI"
56 | },
57 | {
58 | "tag": "音视频相关",
59 | "filename": "audio-video",
60 | "keywords": "WebVR|WebRTC|Video|Audio|图像|音频|视频|直播|摄像头|播放器"
61 | },
62 | {
63 | "tag": "性能优化",
64 | "filename": "optimization",
65 | "keywords": "性能|优化|加载|SEO|Hints|Prefetch|Prerender|Preload"
66 | },
67 | {
68 | "tag": "浏览器相关",
69 | "filename": "browser",
70 | "keywords": "Chrome|Chromium|IE|Firefox|Safari|Webkit|Edge|WebSocket|GET|POST|CORS|URL|浏览器|调试|缓存|跨域|请求|安全|状态码|重绘|重排|渲染"
71 | },
72 | {
73 | "tag": "前端进阶相关",
74 | "filename": "front-end-advanced",
75 | "keywords": "AST|GPU|WebAssembly|Vim|HTTP|算法|全栈"
76 | },
77 | {
78 | "tag": "服务端相关",
79 | "filename": "server",
80 | "keywords": "Nginx|Docker|GraphQL|REST|gRPC"
81 | },
82 | {
83 | "tag": "Git、SVN",
84 | "filename": "git-svn",
85 | "keywords": "Git|SVN"
86 | },
87 | {
88 | "tag": "招聘面试",
89 | "filename": "job-interview",
90 | "keywords": "招聘|面试"
91 | },
92 | {
93 | "tag": "面向对象❤️",
94 | "filename": "oop",
95 | "keywords": "面向对象:"
96 | },
97 | {
98 | "tag": "肺炎疫情",
99 | "filename": "肺炎疫情",
100 | "keywords": "肺炎|肺炎疫情|武汉肺炎:"
101 | },
102 | {
103 | "tag": "其它",
104 | "filename": "other",
105 | "keywords": ""
106 | }
107 | ]
108 |
--------------------------------------------------------------------------------
/site/build/webpack.dev.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const utils = require('./utils')
3 | const webpack = require('webpack')
4 | const config = require('../config')
5 | const merge = require('webpack-merge')
6 | const path = require('path')
7 | const baseWebpackConfig = require('./webpack.base.conf')
8 | const CopyWebpackPlugin = require('copy-webpack-plugin')
9 | const HtmlWebpackPlugin = require('html-webpack-plugin')
10 | const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
11 | const portfinder = require('portfinder')
12 |
13 | const HOST = process.env.HOST
14 | const PORT = process.env.PORT && Number(process.env.PORT)
15 |
16 | const devWebpackConfig = merge(baseWebpackConfig, {
17 | module: {
18 | rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
19 | },
20 | // cheap-module-eval-source-map is faster for development
21 | devtool: config.dev.devtool,
22 |
23 | // these devServer options should be customized in /config/index.js
24 | devServer: {
25 | clientLogLevel: 'warning',
26 | historyApiFallback: {
27 | rewrites: [
28 | { from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
29 | ],
30 | },
31 | hot: true,
32 | contentBase: false, // since we use CopyWebpackPlugin.
33 | compress: true,
34 | host: HOST || config.dev.host,
35 | port: PORT || config.dev.port,
36 | open: config.dev.autoOpenBrowser,
37 | overlay: config.dev.errorOverlay
38 | ? { warnings: false, errors: true }
39 | : false,
40 | publicPath: config.dev.assetsPublicPath,
41 | proxy: config.dev.proxyTable,
42 | quiet: true, // necessary for FriendlyErrorsPlugin
43 | watchOptions: {
44 | poll: config.dev.poll,
45 | }
46 | },
47 | plugins: [
48 | new webpack.DefinePlugin({
49 | 'process.env': require('../config/dev.env')
50 | }),
51 | new webpack.HotModuleReplacementPlugin(),
52 | new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
53 | new webpack.NoEmitOnErrorsPlugin(),
54 | // https://github.com/ampedandwired/html-webpack-plugin
55 | new HtmlWebpackPlugin({
56 | filename: 'index.html',
57 | template: 'index.html',
58 | inject: true
59 | }),
60 | // copy custom static assets
61 | new CopyWebpackPlugin([
62 | {
63 | from: path.resolve(__dirname, '../static'),
64 | to: config.dev.assetsSubDirectory,
65 | ignore: ['.*']
66 | }
67 | ])
68 | ]
69 | })
70 |
71 | module.exports = new Promise((resolve, reject) => {
72 | portfinder.basePort = process.env.PORT || config.dev.port
73 | portfinder.getPort((err, port) => {
74 | if (err) {
75 | reject(err)
76 | } else {
77 | // publish the new Port, necessary for e2e tests
78 | process.env.PORT = port
79 | // add port to devServer config
80 | devWebpackConfig.devServer.port = port
81 |
82 | // Add FriendlyErrorsPlugin
83 | devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
84 | compilationSuccessInfo: {
85 | messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
86 | },
87 | onErrors: config.dev.notifyOnErrors
88 | ? utils.createNotifierCallback()
89 | : undefined
90 | }))
91 |
92 | resolve(devWebpackConfig)
93 | }
94 | })
95 | })
96 |
--------------------------------------------------------------------------------
/server/writemd.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs')
2 | const path = require('path')
3 | const moment = require('moment')
4 | const _ = require('underscore')
5 | const cloneDeep = require('clone-deep')
6 |
7 | const utils = require('./utils')
8 |
9 | const {
10 | RESP_PATH,
11 | RSS_PATH,
12 | LINKS_PATH,
13 | TAGS_PATH,
14 | README_PATH,
15 | README_TEMPLATE_PATH,
16 | TAGS_MD_PATH,
17 | TAGS_TEMPLATE_PATH,
18 | TIMELINE_MD_PATH,
19 | TIMELINE_TEMPLATE_PATH,
20 | DETAILS_TEMPLATE_PATH,
21 | } = utils.PATH
22 |
23 | /**
24 | * 渲染 README.md 文件
25 | */
26 | function handlerREADME(newData){
27 | newData = newData || {
28 | length: 0,
29 | titles: [],
30 | rss: {},
31 | links: {}
32 | }
33 |
34 | let content = fs.readFileSync(README_TEMPLATE_PATH);
35 |
36 | let compiled = _.template(content.toString());
37 |
38 | content = compiled({
39 | newData,
40 | currentDate: utils.getNowDate(),
41 | linksJson: utils.getLinksJson(),
42 | formatTitle: utils.formatTitle,
43 | });
44 |
45 | fs.writeFileSync(README_PATH, content, 'utf-8');
46 | }
47 |
48 | /**
49 | * 渲染 TAGS.md 文件
50 | */
51 | function handlerTags(){
52 | let tags = require(TAGS_PATH);
53 | let data = utils.getLinksJson();
54 |
55 | tags.forEach((tag, i) => {
56 | tags[i].items = [];
57 |
58 | data.forEach((o) => {
59 | o.items.forEach((item) => {
60 | if(!item.rssTitle && (new RegExp(tag.keywords, 'gi')).test(item.title)){
61 | item.rssTitle = o.title;
62 | tags[i].items.push(item);
63 | }
64 | });
65 | });
66 |
67 | // details/tags/file.md
68 | let detailTpl = fs.readFileSync(DETAILS_TEMPLATE_PATH).toString();
69 | let detailCompiled = _.template(detailTpl);
70 | const filename = tag.filename + '.md'
71 |
72 | const detailContent = detailCompiled({
73 | currentDate: utils.getNowDate(),
74 | formatTitle: utils.formatTitle,
75 | title: tags[i].tag,
76 | keywords: tags[i].keywords,
77 | items: tags[i].items
78 | });
79 |
80 | fs.writeFileSync(path.join(RESP_PATH, 'details/tags/', filename), detailContent, 'utf-8');
81 |
82 | });
83 |
84 | let content = fs.readFileSync(TAGS_TEMPLATE_PATH);
85 | let compiled = _.template(content.toString());
86 |
87 | content = compiled({
88 | currentDate: utils.getNowDate(),
89 | formatTitle: utils.formatTitle,
90 | tags
91 | });
92 |
93 | fs.writeFileSync(TAGS_MD_PATH, content, 'utf-8');
94 | }
95 |
96 | function handlerTimeline(){
97 | let dataObj = {}
98 | let dataYears = []
99 | let allLinks = utils.getLinksJson()
100 |
101 | allLinks.forEach((rss) => {
102 | rss.items.forEach((item) => {
103 | let year = item.date.substr(0, 4)
104 | let date = item.date.substr(0, 7)
105 |
106 | if(dataYears.indexOf(year) === -1){
107 | dataYears.push(year)
108 | }
109 |
110 | item.rssTitle = rss.title;
111 | dataObj[date] = dataObj[date] || []
112 | dataObj[date].push(item)
113 | })
114 | })
115 |
116 | let content = fs.readFileSync(TIMELINE_TEMPLATE_PATH);
117 |
118 | let compiled = _.template(content.toString());
119 |
120 | content = compiled({
121 | currentDate: utils.getNowDate(),
122 | dataObj,
123 | formatTitle: utils.formatTitle,
124 | dataYears,
125 | dataKeys: Object.keys(dataObj).sort().reverse()
126 | });
127 |
128 | fs.writeFileSync(TIMELINE_MD_PATH, content, 'utf-8');
129 | }
130 |
131 | /**
132 | * 生成每个详情页面
133 | */
134 | function handlerDetails(newData){
135 | newData = newData || {
136 | length: 0,
137 | titles: [],
138 | rss: {},
139 | links: {}
140 | }
141 | let allLinks = utils.getLinksJson()
142 | let content = fs.readFileSync(DETAILS_TEMPLATE_PATH).toString();
143 | let compiled = _.template(content);
144 |
145 | allLinks.forEach((source) => {
146 | if (source.rss in newData.rss){
147 | source.currentDate = utils.getNowDate()
148 | source.formatTitle = utils.formatTitle
149 |
150 | content = compiled(source);
151 |
152 | let filename = source.title.replace(/[\\\/]/g, '')
153 | filename += '.md'
154 |
155 | fs.writeFileSync(path.join(RESP_PATH, 'details', filename), content, 'utf-8');
156 | }
157 | })
158 | }
159 |
160 | module.exports = function(newData){
161 | handlerREADME(newData)
162 | handlerTags()
163 | handlerTimeline()
164 | handlerDetails(newData)
165 | }
166 |
--------------------------------------------------------------------------------
/data/rss.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "title": "武汉肺炎防疫全纪录(财新网)",
4 | "rss": "https://front-rss.herokuapp.com/coronavirus/caixin"
5 | },
6 | {
7 | "title": "全国新型肺炎疫情实时动态(丁香园)",
8 | "rss": "https://front-rss.herokuapp.com/coronavirus/dxy"
9 | },
10 | {
11 | "title": "Vue社区",
12 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/9891"
13 | },
14 | {
15 | "title": "Vue中文社区",
16 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/10315"
17 | },
18 | {
19 | "title": "VUE全家桶",
20 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/10646"
21 | },
22 | {
23 | "title": "React中文社区",
24 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/10445"
25 | },
26 | {
27 | "title": "前端早读课",
28 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/5760"
29 | },
30 | {
31 | "title": "前端大全",
32 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/65"
33 | },
34 | {
35 | "title": "前端开发",
36 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/29"
37 | },
38 | {
39 | "title": "前端圈",
40 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/166"
41 | },
42 | {
43 | "title": "前端开发博客",
44 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/169"
45 | },
46 | {
47 | "title": "前端大学",
48 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/892"
49 | },
50 | {
51 | "title": "前端外刊评论",
52 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/895"
53 | },
54 | {
55 | "title": "前端之巅",
56 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/154"
57 | },
58 | {
59 | "title": "前端迷",
60 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/9457"
61 | },
62 | {
63 | "title": "全栈前端精选",
64 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/9323"
65 | },
66 | {
67 | "title": "政采云前端团队",
68 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/10195"
69 | },
70 | {
71 | "title": "前端宇宙",
72 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/8801"
73 | },
74 | {
75 | "title": "前端瓶子君",
76 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/10641"
77 | },
78 | {
79 | "title": "程序员成长指北",
80 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/10108"
81 | },
82 | {
83 | "title": "Nodejs技术栈",
84 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/10545"
85 | },
86 | {
87 | "title": "张鑫旭-鑫空间-鑫生活",
88 | "rss": "https://www.zhangxinxu.com/wordpress/feed/"
89 | },
90 | {
91 | "title": "阮一峰的网络日志",
92 | "rss": "http://www.ruanyifeng.com/blog/atom.xml"
93 | },
94 | {
95 | "title": "京东设计中心",
96 | "rss": "http://jdc.jd.com/feed"
97 | },
98 | {
99 | "title": "凹凸实验室",
100 | "rss": "https://aotu.io/atom.xml"
101 | },
102 | {
103 | "title": "奇舞周刊",
104 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/6210"
105 | },
106 | {
107 | "title": "前端日刊",
108 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/5762"
109 | },
110 | {
111 | "title": "前端e进阶",
112 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/10548"
113 | },
114 | {
115 | "title": "互联网架构师",
116 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/6304"
117 | },
118 | {
119 | "title": "InfoQ",
120 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/89"
121 | },
122 | {
123 | "title": "JavaScript",
124 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/893"
125 | },
126 | {
127 | "title": "掘金前端",
128 | "rss": "https://front-rss.herokuapp.com/juejin/category/frontend"
129 | },
130 | {
131 | "title": "前端艺术家&&飞冰早报",
132 | "rss": "https://front-rss.herokuapp.com/jskou/0"
133 | },
134 | {
135 | "title": "印记中文周刊",
136 | "rss": "https://front-rss.herokuapp.com/docschina/jsweekly"
137 | },
138 | {
139 | "title": "编程之上",
140 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/10647"
141 | },
142 | {
143 | "title": "知乎日报",
144 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/198"
145 | },
146 | {
147 | "title": "V2EX",
148 | "rss": "https://front-rss.herokuapp.com/v2ex/topics/latest"
149 | },
150 | {
151 | "title": "技术头条",
152 | "rss": "https://front-rss.herokuapp.com/blogread/newest"
153 | },
154 | {
155 | "title": "开发者头条",
156 | "rss": "https://front-rss.herokuapp.com/toutiao/today"
157 | },
158 | {
159 | "title": "安全热点",
160 | "rss": "https://sec.thief.one/atom.xml"
161 | },
162 | {
163 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/PQDgZ2jW",
164 | "title": "物联网智库"
165 | }
166 | ]
167 |
--------------------------------------------------------------------------------
/server/fetch.js:
--------------------------------------------------------------------------------
1 | const queryString = require('query-string')
2 | const Parser = require('rss-parser')
3 | const moment = require('moment')
4 |
5 | const utils = require('./utils')
6 |
7 | const Fetch = async function(newData, linksJson, linksJsonIndex, jsonItem, rssItem, cb){
8 | let rssArray = rssItem.rss
9 | let done = false;
10 |
11 | if(typeof rssArray === 'string'){
12 | rssArray = [ rssArray ]
13 | }
14 |
15 | while(!done){
16 | await fetchOne(0);
17 | }
18 |
19 | function fetchOne(index, onResolve){
20 | return new Promise((resolve) => {
21 | onResolve = onResolve || resolve;
22 |
23 | let rss = rssArray[index];
24 | let callDone = function(){
25 | onResolve();
26 | done = true;
27 | cb(null, jsonItem);
28 | }
29 |
30 | if(!rss) return callDone();
31 |
32 | let parser = new Parser({
33 | headers: {
34 | 'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1'
35 | },
36 | });
37 |
38 | // 超时处理
39 | let finished = false;
40 | let timer = setTimeout(() => {
41 | if(!finished){
42 | console.log(utils.getNowDate() + ' - 超时 RSS: ' + rss);
43 | finished = true
44 | fetchOne(index+1, onResolve);
45 | }
46 | }, 800000);
47 |
48 | console.log(utils.getNowDate() + ' - 开始 RSS: ' + rss);
49 | parser.parseURL(replaceRss(rss), function(err, feed) {
50 | if(finished) return;
51 | finished = true;
52 | clearTimeout(timer);
53 |
54 | let _items = jsonItem.items || []
55 | let len = _items.length
56 | let items = []
57 |
58 | if(!feed){
59 | console.log(utils.getNowDate() + ' - 失败 RSS: ' + rss);
60 | feed = {};
61 | feed.title = jsonItem.title
62 | feed.link = jsonItem.link
63 | feed.items = []
64 | }
65 |
66 | feed.items.forEach(el => {
67 | let exist = false
68 |
69 | // for taobaofed
70 | if(/https?:\/\/taobaofed\.org/.test(el.link)) {
71 | el.link = el.link.replace(/https?:\/\/taobaofed\.org/, 'https://fed.taobao.org');
72 | }
73 |
74 | for(let i = 0; i < len; i++){
75 | if(isSameLink(_items[i].link, el.link)){
76 | exist = true
77 | break;
78 | }
79 | }
80 |
81 | if(!exist){
82 | let date = moment().format('YYYY-MM-DD')
83 |
84 | try{
85 | date = moment(el.isoDate).format('YYYY-MM-DD')
86 | }catch(e){
87 | }
88 |
89 | let itemObject = {
90 | title: el.title,
91 | link: el.link,
92 | date: date
93 | }
94 |
95 | items.push(itemObject)
96 |
97 | newData.rss[rss] = true
98 | newData.links[el.link] = true
99 |
100 | done = true;
101 | }
102 | });
103 |
104 | feed.title = rssItem.title
105 |
106 | if(items.length){
107 | newData.titles.push(feed.title)
108 | }
109 |
110 | newData.length += items.length
111 |
112 | jsonItem.rss = rss
113 | jsonItem.title = feed.title
114 | jsonItem.link = feed.link
115 | jsonItem.items = items.concat(_items)
116 |
117 | linksJson[linksJsonIndex] = jsonItem
118 |
119 | if(done){
120 | console.log(utils.getNowDate() + ' - 完成 RSS: ' + rss);
121 | callDone();
122 | }else{
123 | fetchOne(index+1, onResolve);
124 | }
125 | })
126 | })
127 | }
128 | }
129 |
130 | function isSameLink(link, compare){
131 | link = link.replace(/&/g, '&');
132 | compare = compare.replace(/&/g, '&');
133 |
134 | const oLink = queryString.parseUrl(link);
135 | const oCompare = queryString.parseUrl(compare);
136 |
137 | if(/mp\.weixin/.test(oLink.url)){
138 | return (oLink.query.sn === oCompare.query.sn)
139 | && (oLink.query.mid === oCompare.query.mid)
140 | }else{
141 | return link === compare
142 | }
143 | }
144 |
145 |
146 | // 加快速度,使用本地的 RSSHub
147 | let useLocalRSSHub = process.argv.indexOf('LOCAL_RSSHub') > -1 || process.argv.indexOf('--LOCAL_RSSHub') > -1
148 | function replaceRss(rss){
149 | if(!useLocalRSSHub) return rss
150 |
151 | if(/rsshub\.app/.test(rss)){
152 | console.log('https://front-rss.herokuapp.com ==> http://127.0.0.1:1200')
153 | }
154 |
155 | return rss.replace('https://front-rss.herokuapp.com', 'http://127.0.0.1:1200')
156 | }
157 |
158 | module.exports = Fetch;
159 |
--------------------------------------------------------------------------------
/site/build/webpack.prod.conf.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const path = require('path')
3 | const utils = require('./utils')
4 | const webpack = require('webpack')
5 | const config = require('../config')
6 | const merge = require('webpack-merge')
7 | const baseWebpackConfig = require('./webpack.base.conf')
8 | const CopyWebpackPlugin = require('copy-webpack-plugin')
9 | const HtmlWebpackPlugin = require('html-webpack-plugin')
10 | const ExtractTextPlugin = require('extract-text-webpack-plugin')
11 | const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
12 | const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
13 |
14 | const env = require('../config/prod.env')
15 |
16 | const webpackConfig = merge(baseWebpackConfig, {
17 | module: {
18 | rules: utils.styleLoaders({
19 | sourceMap: config.build.productionSourceMap,
20 | extract: true,
21 | usePostCSS: true
22 | })
23 | },
24 | devtool: config.build.productionSourceMap ? config.build.devtool : false,
25 | output: {
26 | path: config.build.assetsRoot,
27 | filename: utils.assetsPath('js/[name].[chunkhash].js'),
28 | chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
29 | },
30 | plugins: [
31 | // http://vuejs.github.io/vue-loader/en/workflow/production.html
32 | new webpack.DefinePlugin({
33 | 'process.env': env
34 | }),
35 | new UglifyJsPlugin({
36 | uglifyOptions: {
37 | compress: {
38 | warnings: false
39 | }
40 | },
41 | sourceMap: config.build.productionSourceMap,
42 | parallel: true
43 | }),
44 | // extract css into its own file
45 | new ExtractTextPlugin({
46 | filename: utils.assetsPath('css/[name].[contenthash].css'),
47 | // Setting the following option to `false` will not extract CSS from codesplit chunks.
48 | // Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
49 | // It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
50 | // increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
51 | allChunks: true,
52 | }),
53 | // Compress extracted CSS. We are using this plugin so that possible
54 | // duplicated CSS from different components can be deduped.
55 | new OptimizeCSSPlugin({
56 | cssProcessorOptions: config.build.productionSourceMap
57 | ? { safe: true, map: { inline: false } }
58 | : { safe: true }
59 | }),
60 | // generate dist index.html with correct asset hash for caching.
61 | // you can customize output by editing /index.html
62 | // see https://github.com/ampedandwired/html-webpack-plugin
63 | new HtmlWebpackPlugin({
64 | filename: config.build.index,
65 | template: 'index.html',
66 | inject: true,
67 | minify: {
68 | removeComments: true,
69 | collapseWhitespace: true,
70 | removeAttributeQuotes: true
71 | // more options:
72 | // https://github.com/kangax/html-minifier#options-quick-reference
73 | },
74 | // necessary to consistently work with multiple chunks via CommonsChunkPlugin
75 | chunksSortMode: 'dependency'
76 | }),
77 | // keep module.id stable when vendor modules does not change
78 | new webpack.HashedModuleIdsPlugin(),
79 | // enable scope hoisting
80 | new webpack.optimize.ModuleConcatenationPlugin(),
81 | // split vendor js into its own file
82 | new webpack.optimize.CommonsChunkPlugin({
83 | name: 'vendor',
84 | minChunks (module) {
85 | // any required modules inside node_modules are extracted to vendor
86 | return (
87 | module.resource &&
88 | /\.js$/.test(module.resource) &&
89 | module.resource.indexOf(
90 | path.join(__dirname, '../node_modules')
91 | ) === 0
92 | )
93 | }
94 | }),
95 | // extract webpack runtime and module manifest to its own file in order to
96 | // prevent vendor hash from being updated whenever app bundle is updated
97 | new webpack.optimize.CommonsChunkPlugin({
98 | name: 'manifest',
99 | minChunks: Infinity
100 | }),
101 | // This instance extracts shared chunks from code splitted chunks and bundles them
102 | // in a separate chunk, similar to the vendor chunk
103 | // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
104 | new webpack.optimize.CommonsChunkPlugin({
105 | name: 'app',
106 | async: 'vendor-async',
107 | children: true,
108 | minChunks: 3
109 | }),
110 |
111 | // copy custom static assets
112 | new CopyWebpackPlugin([
113 | {
114 | from: path.resolve(__dirname, '../static'),
115 | to: config.build.assetsSubDirectory,
116 | ignore: ['.*']
117 | }
118 | ])
119 | ]
120 | })
121 |
122 | if (config.build.productionGzip) {
123 | const CompressionWebpackPlugin = require('compression-webpack-plugin')
124 |
125 | webpackConfig.plugins.push(
126 | new CompressionWebpackPlugin({
127 | asset: '[path].gz[query]',
128 | algorithm: 'gzip',
129 | test: new RegExp(
130 | '\\.(' +
131 | config.build.productionGzipExtensions.join('|') +
132 | ')$'
133 | ),
134 | threshold: 10240,
135 | minRatio: 0.8
136 | })
137 | )
138 | }
139 |
140 | if (config.build.bundleAnalyzerReport) {
141 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
142 | webpackConfig.plugins.push(new BundleAnalyzerPlugin())
143 | }
144 |
145 | module.exports = webpackConfig
146 |
--------------------------------------------------------------------------------
/server/links.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "rss": "https://rss.w4ctech.cn/coronavirus/caixin",
4 | "title": "武汉肺炎防疫全纪录(财新网)",
5 | "link": "http://m.app.caixin.com/m_topic_detail/1473.html",
6 | "items": []
7 | },
8 | {
9 | "rss": "https://rss.w4ctech.cn/coronavirus/dxy",
10 | "title": "全国新型肺炎疫情实时动态(丁香园)",
11 | "link": "https://3g.dxy.cn/newh5/view/pneumonia",
12 | "items": []
13 | },
14 | {
15 | "rss": "https://rss.w4ctech.cn/wechat/ershicimi/9891",
16 | "title": "Vue社区",
17 | "link": "https://www.ershicimi.com/a/9891",
18 | "items": []
19 | },
20 | {
21 | "rss": "https://rss.w4ctech.cn/wechat/ershicimi/10315",
22 | "title": "Vue中文社区",
23 | "link": "https://www.ershicimi.com/a/10315",
24 | "items": []
25 | },
26 | {
27 | "rss": "https://rss.w4ctech.cn/wechat/ershicimi/10646",
28 | "title": "VUE全家桶",
29 | "link": "https://www.ershicimi.com/a/10646",
30 | "items": []
31 | },
32 | {
33 | "rss": "https://rss.w4ctech.cn/wechat/ershicimi/10445",
34 | "title": "React中文社区",
35 | "link": "https://www.ershicimi.com/a/10445",
36 | "items": []
37 | },
38 | {
39 | "rss": "https://rss.w4ctech.cn/wechat/ershicimi/5760",
40 | "title": "前端早读课",
41 | "link": "https://www.ershicimi.com/a/5760",
42 | "items": []
43 | },
44 | {
45 | "rss": "https://rss.w4ctech.cn/wechat/ershicimi/65",
46 | "title": "前端大全",
47 | "link": "https://www.ershicimi.com/a/65",
48 | "items": []
49 | },
50 | {
51 | "rss": "https://rss.w4ctech.cn/wechat/ershicimi/29",
52 | "title": "前端开发",
53 | "link": "https://www.ershicimi.com/a/29",
54 | "items": []
55 | },
56 | {
57 | "rss": "https://rss.w4ctech.cn/wechat/ershicimi/166",
58 | "title": "前端圈",
59 | "link": "https://www.ershicimi.com/a/166",
60 | "items": []
61 | },
62 | {
63 | "rss": "https://rss.w4ctech.cn/wechat/ershicimi/169",
64 | "title": "前端开发博客",
65 | "items": [],
66 | "link": "https://www.ershicimi.com/a/169"
67 | },
68 | {
69 | "rss": "https://rss.w4ctech.cn/wechat/ershicimi/892",
70 | "title": "前端大学",
71 | "items": [],
72 | "link": "https://www.ershicimi.com/a/892"
73 | },
74 | {
75 | "rss": "https://rss.w4ctech.cn/wechat/ershicimi/895",
76 | "title": "前端外刊评论",
77 | "items": [],
78 | "link": "https://www.ershicimi.com/a/895"
79 | },
80 | {
81 | "rss": "https://rss.w4ctech.cn/wechat/ershicimi/154",
82 | "title": "前端之巅",
83 | "link": "https://www.ershicimi.com/a/154",
84 | "items": []
85 | },
86 | {
87 | "rss": "https://rss.w4ctech.cn/wechat/ershicimi/9457",
88 | "title": "前端迷",
89 | "link": "https://www.ershicimi.com/a/9457",
90 | "items": []
91 | },
92 | {
93 | "rss": "https://rss.w4ctech.cn/wechat/ershicimi/9323",
94 | "title": "全栈前端精选",
95 | "link": "https://www.ershicimi.com/a/9323",
96 | "items": []
97 | },
98 | {
99 | "rss": "https://rss.w4ctech.cn/wechat/ershicimi/10195",
100 | "title": "政采云前端团队",
101 | "link": "https://www.ershicimi.com/a/10195",
102 | "items": []
103 | },
104 | {
105 | "rss": "https://rss.w4ctech.cn/wechat/ershicimi/8801",
106 | "title": "前端宇宙",
107 | "link": "https://www.ershicimi.com/a/8801",
108 | "items": []
109 | },
110 | {
111 | "rss": "https://rss.w4ctech.cn/wechat/ershicimi/10641",
112 | "title": "前端瓶子君",
113 | "items": [],
114 | "link": "https://www.ershicimi.com/a/10641"
115 | },
116 | {
117 | "rss": "https://rss.w4ctech.cn/wechat/ershicimi/10108",
118 | "title": "程序员成长指北",
119 | "link": "https://www.ershicimi.com/a/10108",
120 | "items": []
121 | },
122 | {
123 | "rss": "https://rss.w4ctech.cn/wechat/ershicimi/10545",
124 | "title": "Nodejs技术栈",
125 | "link": "https://www.ershicimi.com/a/10545",
126 | "items": []
127 | },
128 | {
129 | "rss": "https://www.zhangxinxu.com/wordpress/feed/",
130 | "title": "张鑫旭-鑫空间-鑫生活",
131 | "link": "https://www.zhangxinxu.com/wordpress",
132 | "items": []
133 | },
134 | {
135 | "rss": "http://www.ruanyifeng.com/blog/atom.xml",
136 | "title": "阮一峰的网络日志",
137 | "link": "http://www.ruanyifeng.com/blog/",
138 | "items": []
139 | },
140 | {
141 | "rss": "http://jdc.jd.com/feed",
142 | "title": "京东设计中心",
143 | "items": [],
144 | "link": "https://jdc.jd.com"
145 | },
146 | {
147 | "rss": "https://aotu.io/atom.xml",
148 | "title": "凹凸实验室",
149 | "link": "/atom.xml",
150 | "items": []
151 | },
152 | {
153 | "rss": "https://rss.w4ctech.cn/wechat/ershicimi/6210",
154 | "title": "奇舞周刊",
155 | "link": "https://www.ershicimi.com/a/6210",
156 | "items": []
157 | },
158 | {
159 | "rss": "https://rss.w4ctech.cn/wechat/ershicimi/5762",
160 | "title": "前端日刊",
161 | "link": "https://www.ershicimi.com/a/5762",
162 | "items": []
163 | },
164 | {
165 | "rss": "https://rss.w4ctech.cn/wechat/ershicimi/10548",
166 | "title": "前端e进阶",
167 | "link": "https://www.ershicimi.com/a/10548",
168 | "items": []
169 | },
170 | {
171 | "rss": "https://rss.w4ctech.cn/wechat/ershicimi/6304",
172 | "title": "互联网架构师",
173 | "link": "https://www.ershicimi.com/a/6304",
174 | "items": []
175 | },
176 | {
177 | "rss": "https://rss.w4ctech.cn/wechat/ershicimi/89",
178 | "title": "InfoQ",
179 | "link": "https://www.ershicimi.com/a/89",
180 | "items": []
181 | },
182 | {
183 | "rss": "https://rss.w4ctech.cn/wechat/ershicimi/893",
184 | "title": "JavaScript",
185 | "link": "https://www.ershicimi.com/a/893",
186 | "items": []
187 | },
188 | {
189 | "rss": "https://rss.w4ctech.cn/juejin/category/frontend",
190 | "title": "掘金前端",
191 | "link": "https://juejin.im/welcome/frontend",
192 | "items": []
193 | },
194 | {
195 | "rss": "https://rss.w4ctech.cn/jskou/0",
196 | "title": "前端艺术家&&飞冰早报",
197 | "link": "http://fe.jskou.com/",
198 | "items": []
199 | },
200 | {
201 | "rss": "https://rss.w4ctech.cn/docschina/jsweekly",
202 | "title": "印记中文周刊",
203 | "link": "https://weekly.docschina.org",
204 | "items": []
205 | },
206 | {
207 | "rss": "https://rss.w4ctech.cn/wechat/ershicimi/10647",
208 | "title": "编程之上",
209 | "link": "https://www.ershicimi.com/a/10647",
210 | "items": []
211 | },
212 | {
213 | "rss": "https://rss.w4ctech.cn/wechat/ershicimi/198",
214 | "title": "知乎日报",
215 | "link": "https://www.ershicimi.com/a/198",
216 | "items": []
217 | },
218 | {
219 | "rss": "https://rss.w4ctech.cn/v2ex/topics/latest",
220 | "title": "V2EX",
221 | "link": "https://www.v2ex.com/",
222 | "items": []
223 | },
224 | {
225 | "rss": "https://rss.w4ctech.cn/blogread/newest",
226 | "title": "技术头条",
227 | "link": "http://blogread.cn/news/newest.php",
228 | "items": []
229 | },
230 | {
231 | "rss": "https://rss.w4ctech.cn/toutiao/today",
232 | "title": "开发者头条",
233 | "link": "https://toutiao.io",
234 | "items": []
235 | },
236 | {
237 | "rss": "https://sec.thief.one/atom.xml",
238 | "title": "安全热点",
239 | "link": "https://sec.thief.one",
240 | "items": []
241 | },
242 | {
243 | "rss": "https://rss.w4ctech.cn/wechat/ershicimi/PQDgZ2jW",
244 | "title": "物联网智库",
245 | "link": "https://www.ershicimi.com/p",
246 | "items": []
247 | }
248 | ]
249 |
--------------------------------------------------------------------------------
/TAGS.md:
--------------------------------------------------------------------------------
1 | > 提示:只是根据标题文案简单匹配分类
2 |
3 | :alarm_clock: 更新时间: 2025-12-13 23:00:43。[来源分类](./README.md)、[时间分类](./TIMELINE.md)
4 |
5 | ## 标签分类
6 |
7 | - [React](#react)
8 | - [Vue](#vue)
9 | - [TypeScript](#typescript)
10 | - [Webpack、NPM、构建相关](#webpack、npm、构建相关)
11 | - [NodeJS](#nodejs)
12 | - [小程序](#小程序)
13 | - [移动开发、Flutter相关](#移动开发、flutter相关)
14 | - [游戏开发](#游戏开发)
15 | - [JavaScript](#javascript)
16 | - [CSS](#css)
17 | - [Canvas、SVG、图像](#canvas、svg、图像)
18 | - [音视频相关](#音视频相关)
19 | - [性能优化](#性能优化)
20 | - [浏览器相关](#浏览器相关)
21 | - [前端进阶相关](#前端进阶相关)
22 | - [服务端相关](#服务端相关)
23 | - [Git、SVN](#git、svn)
24 | - [招聘面试](#招聘面试)
25 | - [面向对象❤️](#面向对象❤️)
26 | - [肺炎疫情](#肺炎疫情)
27 | - [其它](#其它)
28 |
29 | ## 文章链接
30 |
31 |
32 |
33 | React
34 |
35 |
36 |
37 |
38 | > 关键字:`React`、`Rax`、`Nerv`、`Redux`、`useEffect`、`Hooks`
39 |
40 |
41 |
42 | - [......【查看更多】......](./details/tags/react.md)
43 |
44 |
45 |
46 |
47 |
48 |
49 | Vue
50 |
51 |
52 |
53 |
54 | > 关键字:`Vue`、`ElementUI`
55 |
56 |
57 |
58 | - [......【查看更多】......](./details/tags/vue.md)
59 |
60 |
61 |
62 |
63 |
64 |
65 | TypeScript
66 |
67 |
68 |
69 |
70 | > 关键字:`TypeScript`
71 |
72 |
73 |
74 | - [......【查看更多】......](./details/tags/typescript.md)
75 |
76 |
77 |
78 |
79 |
80 |
81 | Webpack、NPM、构建相关
82 |
83 |
84 |
85 |
86 | > 关键字:`Webpack`、`Lerna`、`Rollup`、`NPM`、`NPX`、`Yarn`、`Gulp`、`Grunt`、`Babel`、`ESLint`、`TSLint`、`构建`
87 |
88 |
89 |
90 | - [......【查看更多】......](./details/tags/pack-build.md)
91 |
92 |
93 |
94 |
95 |
96 |
97 | NodeJS
98 |
99 |
100 |
101 |
102 | > 关键字:`Node`、`Node.js`、`Express`、`Koa`、`egg.js`、`pandora.js`、`Electron`、`V8`
103 |
104 |
105 |
106 | - [......【查看更多】......](./details/tags/nodejs.md)
107 |
108 |
109 |
110 |
111 |
112 |
113 | 小程序
114 |
115 |
116 |
117 |
118 | > 关键字:`小程序`、`Taro`、`MPVue`、`Wepy`、`Chameleon`
119 |
120 |
121 |
122 | - [......【查看更多】......](./details/tags/miniprogram.md)
123 |
124 |
125 |
126 |
127 |
128 |
129 | 移动开发、Flutter相关
130 |
131 |
132 |
133 |
134 | > 关键字:`Flutter`、`PWA`、`移动开发`
135 |
136 |
137 |
138 | - [......【查看更多】......](./details/tags/dev-mobile.md)
139 |
140 |
141 |
142 |
143 |
144 |
145 | 游戏开发
146 |
147 |
148 |
149 |
150 | > 关键字:`游戏`、`Three.js`、`Create.js`、`Matter.js`
151 |
152 |
153 |
154 | - [......【查看更多】......](./details/tags/dev-game.md)
155 |
156 |
157 |
158 |
159 |
160 |
161 | JavaScript
162 |
163 |
164 |
165 |
166 | > 关键字:`JavaScript`、`ECMAScript`、`JS`、`ES6`、`Promise`、`document`、`await`、`async`、`decorator`、`module`、`import`、`catch`、`console`、`setInterval`、`Worker`、`fetch`、`this`、`bind`、`DataTransfer`、`ArrayBuffer`、`Component`、`DOM`、`H5`、`HTML5`、`组件`、`正则`、`数组`、`事件`、`深拷贝`、`数据代理`、`变量`、`函数式`、`声明式`、`异步`、`表单`、`滚动`、`scroll`、`防抖`、`适配`、`路由`、`模块化`
167 |
168 |
169 |
170 | - [【张鑫旭-鑫空间-鑫生活】介绍下与CSS自定义组件相关的:state函数](https://www.zhangxinxu.com/wordpress/2025/11/css-state-function/)
171 | - [......【查看更多】......](./details/tags/javascript.md)
172 |
173 |
174 |
175 |
176 |
177 |
178 | CSS
179 |
180 |
181 |
182 |
183 | > 关键字:`CSS`、`Sass`、`Less`、`scale`、`transform`、`transition`、`animation`、`border`、`background`、`font-weight`、`font-face`、`flex`、`display`、`position`、`居中`、`动画`
184 |
185 |
186 |
187 | - [【张鑫旭-鑫空间-鑫生活】CSS-progress函数简介](https://www.zhangxinxu.com/wordpress/2025/12/css-progress-function/)
188 | - [【张鑫旭-鑫空间-鑫生活】巧用CSS-::details-content伪元素实现任意展开动画](https://www.zhangxinxu.com/wordpress/2025/11/css-details-target-content-open/)
189 | - [......【查看更多】......](./details/tags/css.md)
190 |
191 |
192 |
193 |
194 |
195 |
196 | Canvas、SVG、图像
197 |
198 |
199 |
200 |
201 | > 关键字:`Canvas`、`SVG`、`WebGL`、`3D`、`PNG`、`WebP`、`RGB`、`GUI`
202 |
203 |
204 |
205 | - [......【查看更多】......](./details/tags/canvas-image.md)
206 |
207 |
208 |
209 |
210 |
211 |
212 | 音视频相关
213 |
214 |
215 |
216 |
217 | > 关键字:`WebVR`、`WebRTC`、`Video`、`Audio`、`图像`、`音频`、`视频`、`直播`、`摄像头`、`播放器`
218 |
219 |
220 |
221 | - [......【查看更多】......](./details/tags/audio-video.md)
222 |
223 |
224 |
225 |
226 |
227 |
228 | 性能优化
229 |
230 |
231 |
232 |
233 | > 关键字:`性能`、`优化`、`加载`、`SEO`、`Hints`、`Prefetch`、`Prerender`、`Preload`
234 |
235 |
236 |
237 | - [......【查看更多】......](./details/tags/optimization.md)
238 |
239 |
240 |
241 |
242 |
243 |
244 | 浏览器相关
245 |
246 |
247 |
248 |
249 | > 关键字:`Chrome`、`Chromium`、`IE`、`Firefox`、`Safari`、`Webkit`、`Edge`、`WebSocket`、`GET`、`POST`、`CORS`、`URL`、`浏览器`、`调试`、`缓存`、`跨域`、`请求`、`安全`、`状态码`、`重绘`、`重排`、`渲染`
250 |
251 |
252 |
253 | - [【张鑫旭-鑫空间-鑫生活】醒醒,该使用CookieStore新建和管理cookie了](https://www.zhangxinxu.com/wordpress/2025/11/js-cookiestore-cookie/)
254 | - [......【查看更多】......](./details/tags/browser.md)
255 |
256 |
257 |
258 |
259 |
260 |
261 | 前端进阶相关
262 |
263 |
264 |
265 |
266 | > 关键字:`AST`、`GPU`、`WebAssembly`、`Vim`、`HTTP`、`算法`、`全栈`
267 |
268 |
269 |
270 | - [......【查看更多】......](./details/tags/front-end-advanced.md)
271 |
272 |
273 |
274 |
275 |
276 |
277 | 服务端相关
278 |
279 |
280 |
281 |
282 | > 关键字:`Nginx`、`Docker`、`GraphQL`、`REST`、`gRPC`
283 |
284 |
285 |
286 | - [......【查看更多】......](./details/tags/server.md)
287 |
288 |
289 |
290 |
291 |
292 |
293 | Git、SVN
294 |
295 |
296 |
297 |
298 | > 关键字:`Git`、`SVN`
299 |
300 |
301 |
302 | - [......【查看更多】......](./details/tags/git-svn.md)
303 |
304 |
305 |
306 |
307 |
308 |
309 | 招聘面试
310 |
311 |
312 |
313 |
314 | > 关键字:`招聘`、`面试`
315 |
316 |
317 |
318 | - [......【查看更多】......](./details/tags/job-interview.md)
319 |
320 |
321 |
322 |
323 |
324 |
325 | 面向对象❤️
326 |
327 |
328 |
329 |
330 | > 关键字:`面向对象`
331 |
332 |
333 |
334 | - [......【查看更多】......](./details/tags/oop.md)
335 |
336 |
337 |
338 |
339 |
340 |
341 | 肺炎疫情
342 |
343 |
344 |
345 |
346 | > 关键字:`肺炎`、`肺炎疫情`、`武汉肺炎`
347 |
348 |
349 |
350 | - [......【查看更多】......](./details/tags/肺炎疫情.md)
351 |
352 |
353 |
354 |
355 |
356 |
357 | 其它
358 |
359 |
360 |
361 |
362 |
363 |
364 | - [【张鑫旭-鑫空间-鑫生活】单IMG标签的图片内阴影效果实现](https://www.zhangxinxu.com/wordpress/2025/12/img-inset-shadow/)
365 | - [......【查看更多】......](./details/tags/other.md)
366 |
367 |
368 |
369 |
370 |
--------------------------------------------------------------------------------
/data/links.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "rss": "https://front-rss.herokuapp.com/coronavirus/caixin",
4 | "title": "武汉肺炎防疫全纪录(财新网)",
5 | "link": "http://m.app.caixin.com/m_topic_detail/1473.html",
6 | "items": []
7 | },
8 | {
9 | "rss": "https://front-rss.herokuapp.com/coronavirus/dxy",
10 | "title": "全国新型肺炎疫情实时动态(丁香园)",
11 | "link": "https://3g.dxy.cn/newh5/view/pneumonia",
12 | "items": []
13 | },
14 | {
15 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/9891",
16 | "title": "Vue社区",
17 | "link": "https://www.ershicimi.com/a/9891",
18 | "items": []
19 | },
20 | {
21 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/10315",
22 | "title": "Vue中文社区",
23 | "link": "https://www.ershicimi.com/a/10315",
24 | "items": []
25 | },
26 | {
27 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/10646",
28 | "title": "VUE全家桶",
29 | "link": "https://www.ershicimi.com/a/10646",
30 | "items": []
31 | },
32 | {
33 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/10445",
34 | "title": "React中文社区",
35 | "link": "https://www.ershicimi.com/a/10445",
36 | "items": []
37 | },
38 | {
39 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/5760",
40 | "title": "前端早读课",
41 | "link": "https://www.ershicimi.com/a/5760",
42 | "items": []
43 | },
44 | {
45 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/65",
46 | "title": "前端大全",
47 | "link": "https://www.ershicimi.com/a/65",
48 | "items": []
49 | },
50 | {
51 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/29",
52 | "title": "前端开发",
53 | "link": "https://www.ershicimi.com/a/29",
54 | "items": []
55 | },
56 | {
57 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/166",
58 | "title": "前端圈",
59 | "link": "https://www.ershicimi.com/a/166",
60 | "items": []
61 | },
62 | {
63 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/169",
64 | "title": "前端开发博客",
65 | "items": [],
66 | "link": "https://www.ershicimi.com/a/169"
67 | },
68 | {
69 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/892",
70 | "title": "前端大学",
71 | "items": [],
72 | "link": "https://www.ershicimi.com/a/892"
73 | },
74 | {
75 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/895",
76 | "title": "前端外刊评论",
77 | "items": [],
78 | "link": "https://www.ershicimi.com/a/895"
79 | },
80 | {
81 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/154",
82 | "title": "前端之巅",
83 | "link": "https://www.ershicimi.com/a/154",
84 | "items": []
85 | },
86 | {
87 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/9457",
88 | "title": "前端迷",
89 | "link": "https://www.ershicimi.com/a/9457",
90 | "items": []
91 | },
92 | {
93 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/9323",
94 | "title": "全栈前端精选",
95 | "link": "https://www.ershicimi.com/a/9323",
96 | "items": []
97 | },
98 | {
99 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/10195",
100 | "title": "政采云前端团队",
101 | "link": "https://www.ershicimi.com/a/10195",
102 | "items": []
103 | },
104 | {
105 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/8801",
106 | "title": "前端宇宙",
107 | "link": "https://www.ershicimi.com/a/8801",
108 | "items": []
109 | },
110 | {
111 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/10641",
112 | "title": "前端瓶子君",
113 | "items": [],
114 | "link": "https://www.ershicimi.com/a/10641"
115 | },
116 | {
117 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/10108",
118 | "title": "程序员成长指北",
119 | "link": "https://www.ershicimi.com/a/10108",
120 | "items": []
121 | },
122 | {
123 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/10545",
124 | "title": "Nodejs技术栈",
125 | "link": "https://www.ershicimi.com/a/10545",
126 | "items": []
127 | },
128 | {
129 | "rss": "https://www.zhangxinxu.com/wordpress/feed/",
130 | "title": "张鑫旭-鑫空间-鑫生活",
131 | "link": "https://www.zhangxinxu.com/wordpress",
132 | "items": [
133 | {
134 | "title": "CSS progress()函数简介",
135 | "link": "https://www.zhangxinxu.com/wordpress/2025/12/css-progress-function/",
136 | "date": "2025-12-12"
137 | },
138 | {
139 | "title": "单IMG标签的图片内阴影效果实现",
140 | "link": "https://www.zhangxinxu.com/wordpress/2025/12/img-inset-shadow/",
141 | "date": "2025-12-04"
142 | },
143 | {
144 | "title": "醒醒,该使用CookieStore新建和管理cookie了",
145 | "link": "https://www.zhangxinxu.com/wordpress/2025/11/js-cookiestore-cookie/",
146 | "date": "2025-11-28"
147 | },
148 | {
149 | "title": "巧用CSS ::details-content伪元素实现任意展开动画",
150 | "link": "https://www.zhangxinxu.com/wordpress/2025/11/css-details-target-content-open/",
151 | "date": "2025-11-24"
152 | },
153 | {
154 | "title": "介绍下与CSS自定义组件相关的:state()函数",
155 | "link": "https://www.zhangxinxu.com/wordpress/2025/11/css-state-function/",
156 | "date": "2025-11-17"
157 | }
158 | ]
159 | },
160 | {
161 | "rss": "http://www.ruanyifeng.com/blog/atom.xml",
162 | "title": "阮一峰的网络日志",
163 | "link": "http://www.ruanyifeng.com/blog/",
164 | "items": []
165 | },
166 | {
167 | "rss": "http://jdc.jd.com/feed",
168 | "title": "京东设计中心",
169 | "items": [],
170 | "link": "https://jdc.jd.com"
171 | },
172 | {
173 | "rss": "https://aotu.io/atom.xml",
174 | "title": "凹凸实验室",
175 | "link": "/atom.xml",
176 | "items": []
177 | },
178 | {
179 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/6210",
180 | "title": "奇舞周刊",
181 | "link": "https://www.ershicimi.com/a/6210",
182 | "items": []
183 | },
184 | {
185 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/5762",
186 | "title": "前端日刊",
187 | "link": "https://www.ershicimi.com/a/5762",
188 | "items": []
189 | },
190 | {
191 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/10548",
192 | "title": "前端e进阶",
193 | "link": "https://www.ershicimi.com/a/10548",
194 | "items": []
195 | },
196 | {
197 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/6304",
198 | "title": "互联网架构师",
199 | "link": "https://www.ershicimi.com/a/6304",
200 | "items": []
201 | },
202 | {
203 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/89",
204 | "title": "InfoQ",
205 | "link": "https://www.ershicimi.com/a/89",
206 | "items": []
207 | },
208 | {
209 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/893",
210 | "title": "JavaScript",
211 | "link": "https://www.ershicimi.com/a/893",
212 | "items": []
213 | },
214 | {
215 | "rss": "https://front-rss.herokuapp.com/juejin/category/frontend",
216 | "title": "掘金前端",
217 | "link": "https://juejin.im/welcome/frontend",
218 | "items": []
219 | },
220 | {
221 | "rss": "https://front-rss.herokuapp.com/jskou/0",
222 | "title": "前端艺术家&&飞冰早报",
223 | "link": "http://fe.jskou.com/",
224 | "items": []
225 | },
226 | {
227 | "rss": "https://front-rss.herokuapp.com/docschina/jsweekly",
228 | "title": "印记中文周刊",
229 | "link": "https://weekly.docschina.org",
230 | "items": []
231 | },
232 | {
233 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/10647",
234 | "title": "编程之上",
235 | "link": "https://www.ershicimi.com/a/10647",
236 | "items": []
237 | },
238 | {
239 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/198",
240 | "title": "知乎日报",
241 | "link": "https://www.ershicimi.com/a/198",
242 | "items": []
243 | },
244 | {
245 | "rss": "https://front-rss.herokuapp.com/v2ex/topics/latest",
246 | "title": "V2EX",
247 | "link": "https://www.v2ex.com/",
248 | "items": []
249 | },
250 | {
251 | "rss": "https://front-rss.herokuapp.com/blogread/newest",
252 | "title": "技术头条",
253 | "link": "http://blogread.cn/news/newest.php",
254 | "items": []
255 | },
256 | {
257 | "rss": "https://front-rss.herokuapp.com/toutiao/today",
258 | "title": "开发者头条",
259 | "link": "https://toutiao.io",
260 | "items": []
261 | },
262 | {
263 | "rss": "https://sec.thief.one/atom.xml",
264 | "title": "安全热点",
265 | "link": "https://sec.thief.one",
266 | "items": []
267 | },
268 | {
269 | "rss": "https://front-rss.herokuapp.com/wechat/ershicimi/PQDgZ2jW",
270 | "title": "物联网智库",
271 | "link": "https://www.ershicimi.com/p",
272 | "items": []
273 | }
274 | ]
--------------------------------------------------------------------------------
/server/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | async@^2.6.1:
6 | version "2.6.3"
7 | resolved "https://registry.npm.taobao.org/async/download/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff"
8 | integrity sha1-1yYl4jRKNlbjo61Pp0n6gymdgv8=
9 | dependencies:
10 | lodash "^4.17.14"
11 |
12 | axios@^0.19.1:
13 | version "0.19.2"
14 | resolved "https://registry.npm.taobao.org/axios/download/axios-0.19.2.tgz#3ea36c5d8818d0d5f8a8a97a6d36b86cdc00cb27"
15 | integrity sha1-PqNsXYgY0NX4qKl6bTa4bNwAyyc=
16 | dependencies:
17 | follow-redirects "1.5.10"
18 |
19 | balanced-match@^1.0.0:
20 | version "1.0.0"
21 | resolved "https://registry.npm.taobao.org/balanced-match/download/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
22 | integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
23 |
24 | brace-expansion@^1.1.7:
25 | version "1.1.11"
26 | resolved "https://registry.npm.taobao.org/brace-expansion/download/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
27 | integrity sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=
28 | dependencies:
29 | balanced-match "^1.0.0"
30 | concat-map "0.0.1"
31 |
32 | clone-deep@^4.0.0:
33 | version "4.0.1"
34 | resolved "https://registry.npm.taobao.org/clone-deep/download/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387"
35 | integrity sha1-wZ/Zvbv4WUK0/ZechNz31fB8I4c=
36 | dependencies:
37 | is-plain-object "^2.0.4"
38 | kind-of "^6.0.2"
39 | shallow-clone "^3.0.0"
40 |
41 | concat-map@0.0.1:
42 | version "0.0.1"
43 | resolved "https://registry.npm.taobao.org/concat-map/download/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
44 | integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=
45 |
46 | debug@=3.1.0:
47 | version "3.1.0"
48 | resolved "https://registry.npm.taobao.org/debug/download/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
49 | integrity sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=
50 | dependencies:
51 | ms "2.0.0"
52 |
53 | debug@^4.0.1:
54 | version "4.1.1"
55 | resolved "https://registry.npm.taobao.org/debug/download/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791"
56 | integrity sha1-O3ImAlUQnGtYnO4FDx1RYTlmR5E=
57 | dependencies:
58 | ms "^2.1.1"
59 |
60 | decode-uri-component@^0.2.0:
61 | version "0.2.0"
62 | resolved "https://registry.npm.taobao.org/decode-uri-component/download/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
63 | integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=
64 |
65 | entities@^1.1.1:
66 | version "1.1.2"
67 | resolved "https://registry.npm.taobao.org/entities/download/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56"
68 | integrity sha1-vfpzUplmTfr9NFKe1PhSKidf6lY=
69 |
70 | follow-redirects@1.5.10:
71 | version "1.5.10"
72 | resolved "https://registry.npm.taobao.org/follow-redirects/download/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a"
73 | integrity sha1-e3qfmuov3/NnhqlP9kPtB/T/Xio=
74 | dependencies:
75 | debug "=3.1.0"
76 |
77 | fs.realpath@^1.0.0:
78 | version "1.0.0"
79 | resolved "https://registry.npm.taobao.org/fs.realpath/download/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
80 | integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8=
81 |
82 | glob@^7.1.3:
83 | version "7.1.6"
84 | resolved "https://registry.npm.taobao.org/glob/download/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
85 | integrity sha1-FB8zuBp8JJLhJVlDB0gMRmeSeKY=
86 | dependencies:
87 | fs.realpath "^1.0.0"
88 | inflight "^1.0.4"
89 | inherits "2"
90 | minimatch "^3.0.4"
91 | once "^1.3.0"
92 | path-is-absolute "^1.0.0"
93 |
94 | inflight@^1.0.4:
95 | version "1.0.6"
96 | resolved "https://registry.npm.taobao.org/inflight/download/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
97 | integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=
98 | dependencies:
99 | once "^1.3.0"
100 | wrappy "1"
101 |
102 | inherits@2:
103 | version "2.0.4"
104 | resolved "https://registry.npm.taobao.org/inherits/download/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
105 | integrity sha1-D6LGT5MpF8NDOg3tVTY6rjdBa3w=
106 |
107 | is-plain-object@^2.0.4:
108 | version "2.0.4"
109 | resolved "https://registry.npm.taobao.org/is-plain-object/download/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677"
110 | integrity sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=
111 | dependencies:
112 | isobject "^3.0.1"
113 |
114 | isobject@^3.0.1:
115 | version "3.0.1"
116 | resolved "https://registry.npm.taobao.org/isobject/download/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
117 | integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8=
118 |
119 | kind-of@^6.0.2:
120 | version "6.0.3"
121 | resolved "https://registry.npm.taobao.org/kind-of/download/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
122 | integrity sha1-B8BQNKbDSfoG4k+jWqdttFgM5N0=
123 |
124 | later@^1.2.0:
125 | version "1.2.0"
126 | resolved "https://registry.npm.taobao.org/later/download/later-1.2.0.tgz#f2cf6c4dd7956dd2f520adf0329836e9876bad0f"
127 | integrity sha1-8s9sTdeVbdL1IK3wMpg26YdrrQ8=
128 |
129 | lodash@^4.17.14:
130 | version "4.17.15"
131 | resolved "https://registry.npm.taobao.org/lodash/download/lodash-4.17.15.tgz?cache=0&sync_timestamp=1577793955950&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flodash%2Fdownload%2Flodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548"
132 | integrity sha1-tEf2ZwoEVbv+7dETku/zMOoJdUg=
133 |
134 | minimatch@^3.0.4:
135 | version "3.0.4"
136 | resolved "https://registry.npm.taobao.org/minimatch/download/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
137 | integrity sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=
138 | dependencies:
139 | brace-expansion "^1.1.7"
140 |
141 | moment@^2.22.2:
142 | version "2.24.0"
143 | resolved "https://registry.npm.taobao.org/moment/download/moment-2.24.0.tgz#0d055d53f5052aa653c9f6eb68bb5d12bf5c2b5b"
144 | integrity sha1-DQVdU/UFKqZTyfbraLtdEr9cK1s=
145 |
146 | ms@2.0.0:
147 | version "2.0.0"
148 | resolved "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
149 | integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
150 |
151 | ms@^2.1.1:
152 | version "2.1.2"
153 | resolved "https://registry.npm.taobao.org/ms/download/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
154 | integrity sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk=
155 |
156 | once@^1.3.0:
157 | version "1.4.0"
158 | resolved "https://registry.npm.taobao.org/once/download/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
159 | integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E=
160 | dependencies:
161 | wrappy "1"
162 |
163 | path-is-absolute@^1.0.0:
164 | version "1.0.1"
165 | resolved "https://registry.npm.taobao.org/path-is-absolute/download/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
166 | integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
167 |
168 | query-string@^6.8.1:
169 | version "6.10.1"
170 | resolved "https://registry.npm.taobao.org/query-string/download/query-string-6.10.1.tgz?cache=0&sync_timestamp=1579245592551&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fquery-string%2Fdownload%2Fquery-string-6.10.1.tgz#30b3505f6fca741d5ae541964d1b3ae9dc2a0de8"
171 | integrity sha1-MLNQX2/KdB1a5UGWTRs66dwqDeg=
172 | dependencies:
173 | decode-uri-component "^0.2.0"
174 | split-on-first "^1.0.0"
175 | strict-uri-encode "^2.0.0"
176 |
177 | rimraf@^3.0.0:
178 | version "3.0.0"
179 | resolved "https://registry.npm.taobao.org/rimraf/download/rimraf-3.0.0.tgz#614176d4b3010b75e5c390eb0ee96f6dc0cebb9b"
180 | integrity sha1-YUF21LMBC3Xlw5DrDulvbcDOu5s=
181 | dependencies:
182 | glob "^7.1.3"
183 |
184 | rss-parser@^3.4.3:
185 | version "3.7.3"
186 | resolved "https://registry.npm.taobao.org/rss-parser/download/rss-parser-3.7.3.tgz#961cd155ca26cb2ba8f52aa7f2321099b8b5ecf0"
187 | integrity sha1-lhzRVcomyyuo9Sqn8jIQmbi17PA=
188 | dependencies:
189 | entities "^1.1.1"
190 | xml2js "^0.4.19"
191 |
192 | sax@>=0.6.0:
193 | version "1.2.4"
194 | resolved "https://registry.npm.taobao.org/sax/download/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
195 | integrity sha1-KBYjTiN4vdxOU1T6tcqold9xANk=
196 |
197 | shallow-clone@^3.0.0:
198 | version "3.0.1"
199 | resolved "https://registry.npm.taobao.org/shallow-clone/download/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3"
200 | integrity sha1-jymBrZJTH1UDWwH7IwdppA4C76M=
201 | dependencies:
202 | kind-of "^6.0.2"
203 |
204 | simple-git@^1.102.0:
205 | version "1.130.0"
206 | resolved "https://registry.npm.taobao.org/simple-git/download/simple-git-1.130.0.tgz#b689c4163bc021df563a81f256de54482005195d"
207 | integrity sha1-tonEFjvAId9WOoHyVt5USCAFGV0=
208 | dependencies:
209 | debug "^4.0.1"
210 |
211 | split-on-first@^1.0.0:
212 | version "1.1.0"
213 | resolved "https://registry.npm.taobao.org/split-on-first/download/split-on-first-1.1.0.tgz?cache=0&sync_timestamp=1573632118941&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fsplit-on-first%2Fdownload%2Fsplit-on-first-1.1.0.tgz#f610afeee3b12bce1d0c30425e76398b78249a5f"
214 | integrity sha1-9hCv7uOxK84dDDBCXnY5i3gkml8=
215 |
216 | strict-uri-encode@^2.0.0:
217 | version "2.0.0"
218 | resolved "https://registry.npm.taobao.org/strict-uri-encode/download/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546"
219 | integrity sha1-ucczDHBChi9rFC3CdLvMWGbONUY=
220 |
221 | underscore@^1.12.1:
222 | version "1.12.1"
223 | resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.12.1.tgz#7bb8cc9b3d397e201cf8553336d262544ead829e"
224 | integrity sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==
225 |
226 | wrappy@1:
227 | version "1.0.2"
228 | resolved "https://registry.npm.taobao.org/wrappy/download/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
229 | integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=
230 |
231 | xml2js@^0.4.19:
232 | version "0.4.23"
233 | resolved "https://registry.npm.taobao.org/xml2js/download/xml2js-0.4.23.tgz#a0c69516752421eb2ac758ee4d4ccf58843eac66"
234 | integrity sha1-oMaVFnUkIesqx1juTUzPWIQ+rGY=
235 | dependencies:
236 | sax ">=0.6.0"
237 | xmlbuilder "~11.0.0"
238 |
239 | xmlbuilder@~11.0.0:
240 | version "11.0.1"
241 | resolved "https://registry.npm.taobao.org/xmlbuilder/download/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3"
242 | integrity sha1-vpuuHIoEbnazESdyY0fQrXACvrM=
243 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
4 |
5 | ##
6 |
7 | - 项目目的:每天定时抓取最新前端技术文章,并推送到 GitHub 方便查看
8 | - 文章来源:RSS 订阅源
9 | - 定时抓取:每30分钟一次
10 | - 文章分类:[标签分类](./TAGS.md)、[时间分类](./TIMELINE.md)
11 |
12 | ##
13 |
14 | :alarm_clock: 更新时间: 2025-12-13 23:00:43,:rocket: 更新条数: +5,  表示有更新
15 |
16 | ## 来源分类
17 |
18 | - [武汉肺炎防疫全纪录财新网](#武汉肺炎防疫全纪录财新网)
19 | - [全国新型肺炎疫情实时动态丁香园](#全国新型肺炎疫情实时动态丁香园)
20 | - [Vue社区](#vue社区)
21 | - [Vue中文社区](#vue中文社区)
22 | - [VUE全家桶](#vue全家桶)
23 | - [React中文社区](#react中文社区)
24 | - [前端早读课](#前端早读课)
25 | - [前端大全](#前端大全)
26 | - [前端开发](#前端开发)
27 | - [前端圈](#前端圈)
28 | - [前端开发博客](#前端开发博客)
29 | - [前端大学](#前端大学)
30 | - [前端外刊评论](#前端外刊评论)
31 | - [前端之巅](#前端之巅)
32 | - [前端迷](#前端迷)
33 | - [全栈前端精选](#全栈前端精选)
34 | - [政采云前端团队](#政采云前端团队)
35 | - [前端宇宙](#前端宇宙)
36 | - [前端瓶子君](#前端瓶子君)
37 | - [程序员成长指北](#程序员成长指北)
38 | - [Nodejs技术栈](#nodejs技术栈)
39 | - [张鑫旭-鑫空间-鑫生活](#张鑫旭-鑫空间-鑫生活)
40 | - [阮一峰的网络日志](#阮一峰的网络日志)
41 | - [京东设计中心](#京东设计中心)
42 | - [凹凸实验室](#凹凸实验室)
43 | - [奇舞周刊](#奇舞周刊)
44 | - [前端日刊](#前端日刊)
45 | - [前端e进阶](#前端e进阶)
46 | - [互联网架构师](#互联网架构师)
47 | - [InfoQ](#infoq)
48 | - [JavaScript](#javascript)
49 | - [掘金前端](#掘金前端)
50 | - [前端艺术家&&飞冰早报](#前端艺术家&&飞冰早报)
51 | - [印记中文周刊](#印记中文周刊)
52 | - [编程之上](#编程之上)
53 | - [知乎日报](#知乎日报)
54 | - [V2EX](#v2ex)
55 | - [技术头条](#技术头条)
56 | - [开发者头条](#开发者头条)
57 | - [安全热点](#安全热点)
58 | - [物联网智库](#物联网智库)
59 |
60 | ## 文章链接
61 |
62 |
63 |
64 | 武汉肺炎防疫全纪录财新网
65 |
66 |
67 |
68 | - [......【查看更多】......](./details/武汉肺炎防疫全纪录(财新网).md)
69 |
70 |
71 |
72 |
73 |
74 |
75 | 全国新型肺炎疫情实时动态丁香园
76 |
77 |
78 |
79 | - [......【查看更多】......](./details/全国新型肺炎疫情实时动态(丁香园).md)
80 |
81 |
82 |
83 |
84 |
85 |
86 | Vue社区
87 |
88 |
89 |
90 | - [......【查看更多】......](./details/Vue社区.md)
91 |
92 |
93 |
94 |
95 |
96 |
97 | Vue中文社区
98 |
99 |
100 |
101 | - [......【查看更多】......](./details/Vue中文社区.md)
102 |
103 |
104 |
105 |
106 |
107 |
108 | VUE全家桶
109 |
110 |
111 |
112 | - [......【查看更多】......](./details/VUE全家桶.md)
113 |
114 |
115 |
116 |
117 |
118 |
119 | React中文社区
120 |
121 |
122 |
123 | - [......【查看更多】......](./details/React中文社区.md)
124 |
125 |
126 |
127 |
128 |
129 |
130 | 前端早读课
131 |
132 |
133 |
134 | - [......【查看更多】......](./details/前端早读课.md)
135 |
136 |
137 |
138 |
139 |
140 |
141 | 前端大全
142 |
143 |
144 |
145 | - [......【查看更多】......](./details/前端大全.md)
146 |
147 |
148 |
149 |
150 |
151 |
152 | 前端开发
153 |
154 |
155 |
156 | - [......【查看更多】......](./details/前端开发.md)
157 |
158 |
159 |
160 |
161 |
162 |
163 | 前端圈
164 |
165 |
166 |
167 | - [......【查看更多】......](./details/前端圈.md)
168 |
169 |
170 |
171 |
172 |
173 |
174 | 前端开发博客
175 |
176 |
177 |
178 | - [......【查看更多】......](./details/前端开发博客.md)
179 |
180 |
181 |
182 |
183 |
184 |
185 | 前端大学
186 |
187 |
188 |
189 | - [......【查看更多】......](./details/前端大学.md)
190 |
191 |
192 |
193 |
194 |
195 |
196 | 前端外刊评论
197 |
198 |
199 |
200 | - [......【查看更多】......](./details/前端外刊评论.md)
201 |
202 |
203 |
204 |
205 |
206 |
207 | 前端之巅
208 |
209 |
210 |
211 | - [......【查看更多】......](./details/前端之巅.md)
212 |
213 |
214 |
215 |
216 |
217 |
218 | 前端迷
219 |
220 |
221 |
222 | - [......【查看更多】......](./details/前端迷.md)
223 |
224 |
225 |
226 |
227 |
228 |
229 | 全栈前端精选
230 |
231 |
232 |
233 | - [......【查看更多】......](./details/全栈前端精选.md)
234 |
235 |
236 |
237 |
238 |
239 |
240 | 政采云前端团队
241 |
242 |
243 |
244 | - [......【查看更多】......](./details/政采云前端团队.md)
245 |
246 |
247 |
248 |
249 |
250 |
251 | 前端宇宙
252 |
253 |
254 |
255 | - [......【查看更多】......](./details/前端宇宙.md)
256 |
257 |
258 |
259 |
260 |
261 |
262 | 前端瓶子君
263 |
264 |
265 |
266 | - [......【查看更多】......](./details/前端瓶子君.md)
267 |
268 |
269 |
270 |
271 |
272 |
273 | 程序员成长指北
274 |
275 |
276 |
277 | - [......【查看更多】......](./details/程序员成长指北.md)
278 |
279 |
280 |
281 |
282 |
283 |
284 | Nodejs技术栈
285 |
286 |
287 |
288 | - [......【查看更多】......](./details/Nodejs技术栈.md)
289 |
290 |
291 |
292 |
293 |
294 |
295 | 张鑫旭-鑫空间-鑫生活
296 |
297 |
298 |
299 | - [2025-12-12-CSS-progress函数简介](https://www.zhangxinxu.com/wordpress/2025/12/css-progress-function/) 
300 | - [2025-12-04-单IMG标签的图片内阴影效果实现](https://www.zhangxinxu.com/wordpress/2025/12/img-inset-shadow/) 
301 | - [2025-11-28-醒醒,该使用CookieStore新建和管理cookie了](https://www.zhangxinxu.com/wordpress/2025/11/js-cookiestore-cookie/) 
302 | - [2025-11-24-巧用CSS-::details-content伪元素实现任意展开动画](https://www.zhangxinxu.com/wordpress/2025/11/css-details-target-content-open/) 
303 | - [2025-11-17-介绍下与CSS自定义组件相关的:state函数](https://www.zhangxinxu.com/wordpress/2025/11/css-state-function/) 
304 | - [......【查看更多】......](./details/张鑫旭-鑫空间-鑫生活.md)
305 |
306 |
307 |
308 |
309 |
310 |
311 | 阮一峰的网络日志
312 |
313 |
314 |
315 | - [......【查看更多】......](./details/阮一峰的网络日志.md)
316 |
317 |
318 |
319 |
320 |
321 |
322 | 京东设计中心
323 |
324 |
325 |
326 | - [......【查看更多】......](./details/京东设计中心.md)
327 |
328 |
329 |
330 |
331 |
332 |
333 | 凹凸实验室
334 |
335 |
336 |
337 | - [......【查看更多】......](./details/凹凸实验室.md)
338 |
339 |
340 |
341 |
342 |
343 |
344 | 奇舞周刊
345 |
346 |
347 |
348 | - [......【查看更多】......](./details/奇舞周刊.md)
349 |
350 |
351 |
352 |
353 |
354 |
355 | 前端日刊
356 |
357 |
358 |
359 | - [......【查看更多】......](./details/前端日刊.md)
360 |
361 |
362 |
363 |
364 |
365 |
366 | 前端e进阶
367 |
368 |
369 |
370 | - [......【查看更多】......](./details/前端e进阶.md)
371 |
372 |
373 |
374 |
375 |
376 |
377 | 互联网架构师
378 |
379 |
380 |
381 | - [......【查看更多】......](./details/互联网架构师.md)
382 |
383 |
384 |
385 |
386 |
387 |
388 | InfoQ
389 |
390 |
391 |
392 | - [......【查看更多】......](./details/InfoQ.md)
393 |
394 |
395 |
396 |
397 |
398 |
399 | JavaScript
400 |
401 |
402 |
403 | - [......【查看更多】......](./details/JavaScript.md)
404 |
405 |
406 |
407 |
408 |
409 |
410 | 掘金前端
411 |
412 |
413 |
414 | - [......【查看更多】......](./details/掘金前端.md)
415 |
416 |
417 |
418 |
419 |
420 |
421 | 前端艺术家&&飞冰早报
422 |
423 |
424 |
425 | - [......【查看更多】......](./details/前端艺术家&&飞冰早报.md)
426 |
427 |
428 |
429 |
430 |
431 |
432 | 印记中文周刊
433 |
434 |
435 |
436 | - [......【查看更多】......](./details/印记中文周刊.md)
437 |
438 |
439 |
440 |
441 |
442 |
443 | 编程之上
444 |
445 |
446 |
447 | - [......【查看更多】......](./details/编程之上.md)
448 |
449 |
450 |
451 |
452 |
453 |
454 | 知乎日报
455 |
456 |
457 |
458 | - [......【查看更多】......](./details/知乎日报.md)
459 |
460 |
461 |
462 |
463 |
464 |
465 | V2EX
466 |
467 |
468 |
469 | - [......【查看更多】......](./details/V2EX.md)
470 |
471 |
472 |
473 |
474 |
475 |
476 | 技术头条
477 |
478 |
479 |
480 | - [......【查看更多】......](./details/技术头条.md)
481 |
482 |
483 |
484 |
485 |
486 |
487 | 开发者头条
488 |
489 |
490 |
491 | - [......【查看更多】......](./details/开发者头条.md)
492 |
493 |
494 |
495 |
496 |
497 |
498 | 安全热点
499 |
500 |
501 |
502 | - [......【查看更多】......](./details/安全热点.md)
503 |
504 |
505 |
506 |
507 |
508 |
509 | 物联网智库
510 |
511 |
512 |
513 | - [......【查看更多】......](./details/物联网智库.md)
514 |
515 |
516 |
517 |
518 |
519 | ## 其它
520 | 感谢 [RSSHub](https://github.com/DIYgod/RSSHub) 提供的微信公众号 RSS 链接 Fork自 [ChanceYu](https://github.com/ChanceYu/front-end-rss)
521 |
--------------------------------------------------------------------------------
/site/src/components/loading.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
{{parentMessage}}
5 |
6 |
7 |
8 |
27 |
56 |
--------------------------------------------------------------------------------
/site/src/components/Index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |

5 |
6 |
7 |
8 |
9 |
10 | 热门搜索
11 |
16 | {{item}}
17 |
18 |
19 |
20 | 发布时间
21 |
27 | {{item.text}}
28 |
29 |
30 |
31 | 文章来源
32 |
39 |
40 |
41 | 文章分类
42 |
49 |
50 |
51 |
52 |
60 | 筛选
61 | 搜索
62 |
63 |
64 |
96 |
97 |
98 |
99 |
100 |
347 |
348 |
668 |
--------------------------------------------------------------------------------