Project Name | Stars | Downloads | Repos Using This | Packages Using This | Most Recent Commit | Total Releases | Latest Release | Open Issues | License | Language |
---|---|---|---|---|---|---|---|---|---|---|
Coolify | 7,821 | 21 hours ago | 266 | apache-2.0 | Svelte | |||||
An open-source & self-hostable Heroku / Netlify alternative. | ||||||||||
Handbook | 4,066 | 22 days ago | 75 | Markdown | ||||||
放置我的笔记、搜集、摘录、实践,保持好奇心。看文需谨慎,后果很严重。 | ||||||||||
Crate | 2,374 | 4 months ago | mit | JavaScript | ||||||
👕 👖 📦 A sample web and mobile application built with Node, Express, React, React Native, Redux and GraphQL. Very basic replica of stitchfix.com / krate.in (allows users to get monthly subscription of trendy clothes and accessories). | ||||||||||
Matterwiki | 2,067 | 2 years ago | 49 | mit | JavaScript | |||||
A simple and beautiful wiki for teams | ||||||||||
Spring Security React Ant Design Polls App | 1,617 | 3 months ago | 45 | Java | ||||||
Full Stack Polls App built using Spring Boot, Spring Security, JWT, React, and Ant Design | ||||||||||
React Redux Flask | 1,411 | 2 years ago | 11 | mit | JavaScript | |||||
Boilerplate application for a Python/Flask JWT Backend and a Javascript/React/Redux Front-End with Material UI. | ||||||||||
Chartbrew | 1,299 | 23 days ago | 34 | mit | JavaScript | |||||
Open-source web platform used to create live reporting dashboards from APIs, MongoDB, Firestore, MySQL, PostgreSQL, and more 📈📊 | ||||||||||
Owid Grapher | 1,178 | 4 days ago | 235 | mit | TypeScript | |||||
A platform for creating interactive data visualizations | ||||||||||
Fullstack Graphql | 953 | 2 years ago | mit | JavaScript | ||||||
🌈 Simple Fullstack GraphQL Application. API built with Express + GraphQL + Sequelize (supports MySQL, Postgres, Sqlite and MSSQL). WebApp built with React + Redux to access the API. Written in ES6 using Babel + Webpack. | ||||||||||
Ghchat | 920 | 5 months ago | 52 | mit | JavaScript | |||||
:octocat: 📱A chat application for GitHub. React + PWA + Node(koa2) + Typescripts + Mysql + Socket.io |
利用react服务端框架next.js写的博客,喜欢就给个Star支持一下。 Weibozzz/next-blog 线上地址: http://www.liuweibo.cn 本项目使用next.js经验分享:http://www.liuweibo.cn/p/206 另外还有一个仓库,建立自己的前端知识体系:https://github.com/Weibozzz/Weibozzz.github.io
软件架构说明
react.js next.js antd mysql node koa2 fetch
进入config文件夹下的env.js的isShow设置为true,这里只是调用了我自己线上的接口,当然你 只能看不能修改接口哦。如果为false则调不到接口,需要自己去写接口。
cnpm i
npm run dev
cnpm i
npm run build
npm start
完全借助于 next.js 开发的个人网站,线上地址 http://www.liuweibo.cn 总结一下开发完成后的心得和使用体会。gtihub源码Weibozzz/next-blog。喜欢就给个Star支持一下。
这里就只讲重点了
server.js
这里用的官方提供的express
,同时开启gzip
压缩
const express = require('express')
const next = require('next')
const compression = require('compression')
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
let port= dev?4322:80
app.prepare()
.then(() => {
const server = express()
if (!dev) {
server.use(compression()) //gzip
}
//文章二级页面
server.get('/p/:id', (req, res) => {
const actualPage = '/detail'
const queryParams = { id: req.params.id }
app.render(req, res, actualPage, queryParams)
})
server.get('*', (req, res) => {
return handle(req, res)
})
server.listen(port, (err) => {
if (err) throw err
console.log('> Ready on http://localhost ' port)
})
})
.catch((ex) => {
process.exit(1)
})
用于传递redux数据,store就和普通react用法一样了,还有header和footer可以放在这里,同理还有_err.js
用于处理404页面
import App, {Container} from 'next/app'
import React from 'react'
import {withRouter} from 'next/router' // 接入next的router
import withReduxStore from '../lib/with-redux-store' // 接入next的redux
import {Provider} from 'react-redux'
class MyApp extends App {
render() {
const {Component, pageProps, reduxStore, router: {pathname}} = this.props;
return (
<Container>
<Provider store={reduxStore}>
<Component {...myPageProps} />
</Provider>
</Container>
)
}
}
export default withReduxStore(withRouter(MyApp))
link
用于跳转页面,利用as把原本的http://***.com?id=1变为漂亮的 /id/1head
可以嵌套meta标签进行seoimport dynamic from 'next/dynamic';
//不需要seo
const DynasicTopTipsNoSsr = dynamic(import('../../components/TopTips'),{
ssr:false
})
import React, {Component} from 'react'
import {connect} from 'react-redux'
import Router from 'next/router'
import 'whatwg-fetch' // 用于fetch请求数据
import Link from 'next/link'; // next的跳转link
import Head from 'next/head' // next的跳转head可用于seo
class Blog extends Component {
render() {
return (
<div className="Blog">
<Head>
<title>{BLOG_TXT}»{COMMON_TITLE}</title>
</Head>
<MyLayout>
<Link as={`/Blog/${current}`} href={`/Blog?id=${current}`}>
<a onClick={this.onClickPageChange.bind(this)}>{current}</a>
</Link>
</MyLayout>
</div>
)
}
}
//这里才是重点,getInitialProps方法来请求数据进行渲染,达到服务端渲染的目的
Blog.getInitialProps = async function (context) {
const {id = 1} = context.query
let queryStringObj = {
type: ALL,
num: id,
pageNum
}
let queryTotalString = {type: ALL};
const pageBlog = await fetch(getBlogUrl(queryStringObj))
const pageBlogData = await pageBlog.json()
return {pageBlogData}
}
// 这里根据需要传入redux
const mapStateToProps = state => {
const {res, searchData, searchTotalData} = state
return {res, searchData, searchTotalData};
}
export default connect(mapStateToProps)(Blog)
根目录创建static
文件夹,这里是强制要求,否则加载不到静态资源
antd-custom.less
@primary-color: #722ED0;
@layout-header-height: 40px;
@border-radius-base: 0px;
styles.less
@import "~antd/dist/antd.less";
@import "./antd-custom.less";
最后统一配置在公共head
<Head>
<meta charSet="utf-8"/>
<meta httpEquiv="X-UA-Compatible" content="IE=edge, chrome=1"/>
<meta name="viewport"
content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no"/>
<meta name="renderer" content="webkit"/>
<meta httpEquiv="description" content="刘伟波-伟波前端"/>
<meta name="author" content="刘伟波,liuweibo"/>
<link rel='stylesheet' href='/_next/static/style.css'/>
<link rel='stylesheet' type='text/css' href='/static/nprogress.css' />
<link rel='shortcut icon' type='image/x-icon' href='/static/favicon.ico' />
</Head>
.babelrc
文件
{
"presets": ["next/babel"],
"plugins": [
"transform-decorators-legacy",
[
"import",
{
"libraryName": "antd",
"style": "less"
}
]
]
}
next.config.js
文件配置
const withLess = require('@zeit/next-less')
module.exports = withLess(
{
lessLoaderOptions: {
javascriptEnabled: true,
cssModules: true,
}
}
)
感觉和vue
的scope
一样,style
的jsx
,加了global
为全局,否则只在这里生效
render() {
return (
<Container>
<Provider store={reduxStore}>
<Component {...myPageProps} />
</Provider>
<style jsx global>{`
.fl{
float: left;
}
.fr{
float: right;
}
`}</style>
</Container>
)
import Router from 'next/router'
import NProgress from 'nprogress'
Router.onRouteChangeStart = (url) => {
NProgress.start()
}
Router.onRouteChangeComplete = () => NProgress.done()
Router.onRouteChangeError = () => NProgress.done()
使用只需要marked('放入markdown字符串');
import marked from 'marked'
import hljs from 'highlight.js';
hljs.configure({
tabReplace: ' ',
classPrefix: 'hljs-',
languages: ['CSS', 'HTML, XML', 'JavaScript', 'PHP', 'Python', 'Stylus', 'TypeScript', 'Markdown']
})
marked.setOptions({
highlight: (code) => hljs.highlightAuto(code).value,
gfm: true,
tables: true,
breaks: false,
pedantic: false,
sanitize: true,
smartLists: true,
smartypants: false
});
next.config.js
文件配置
module.exports = {
webpack (config, ...args) {
return config;
}
}
config.resolve.alias = {
...config.resolve.alias,
'@': path.resolve(__dirname, './'),
}
config.plugins.push(
new webpack.DefinePlugin({
'process.env.NODE_ENV': process.env.NODE_ENV
})
)
config.module.rules.push(
{
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'babel-loader'
},
{
loader: '@svgr/webpack',
options: {
babel: false,
icon: true
}
}
]
}
)
config = withCSS()
.webpack(config, ...args)
config = withLess()
.webpack(config, ...args)
const loaderUtils = require('loader-utils')
const fs = require('fs')
const path = require('path')
const cssModuleRegex = /\.module\.less$/
config = withLess(
// 开启 css module 自定义
{
cssModules: true,
cssLoaderOptions: {
importLoaders: 1,
minimize: !args[0].dev,
getLocalIdent: (loaderContext, _, localName, options) => {
const fileName = path.basename(loaderContext.resourcePath)
if (cssModuleRegex.test(fileName)) {
const content = fs.readFileSync(loaderContext.resourcePath)
.toString()
const name = fileName.replace(/\.[^/.]+$/, '')
const hash = args[0].dev ? `${name}___[hash:base64:5]` : '[hash:base64:5]'
const fileNameHash = loaderUtils.interpolateName(
loaderContext,
hash,
{ content }
)
return fileNameHash
}
return localName
}
}
}
)
const withBundleAnalyzer = require('@next/bundle-analyzer')({
enabled: process.env.ANALYZE === 'true'
})
config = withBundleAnalyzer({})
.webpack(config, ...args)
)
访问量大的时候要做数据缓存
cdn node查看图片日期
配置图片描述和更改
上传图片高质量暂未支持上传,上传代码改进
上传为刚好1M bug
登陆后支持收藏文章和修改评论
发表文章如果上一篇文章被删除,自增id不是自加1,需要去查询数据库
填写markdown代码高亮,类似于掘金
versions当天的要合并
contentEditable
github:https://github.com/Weibozzz
segmentfault:https://segmentfault.com/u/weibozzz
公众平台:伟波前端
作者:刘伟波
链接:http://www.liuweibo.cn/p/206
来源:刘伟波博客
本文原创版权属于刘伟波 ,转载请注明出处,谢谢合作