shuvijs / shuvi Goto Github PK
View Code? Open in Web Editor NEWNextjs, but for SPA, no server required
Home Page: https://shuvijs.github.io/shuvijs.org/
Nextjs, but for SPA, no server required
Home Page: https://shuvijs.github.io/shuvijs.org/
Create a new eslint plugin with custom rules so that user can follow.
no-process-electron
Disallow the use of
process.electron
This rule is aimed at discouraging use of process.electron
to avoid complex cross-platform code. As such, it will warn whenever process.electron
is used.
// components/Layout.js
// Unexpected use of process.electron (at 8:14)
const link = process.electron ? "a" : "b";
// -------------^
It is recommended to use platform-specific extensions.
- components/Layout.js
+ components/Layout/index.web.js
+ components/Layout/index.electron.js
// components/Layout/index.web.js
const link = "b";
// components/Layout/index.electron.js
const link = "a";
It should prompt error or prompt to use different port
Scenario:
Run caviar-shuvi app and run spa shuvi app together. Both are able to run
this is low priority, will revisit later on.
我们发现,如果在client side路由导航时,loader 中使用redirect,那么跳转之后,浏览器历史会发生错误。
假设,有/a,/b,/c 三个页面,其中,a 页面有一个link按钮,可以跳转到b。b 的 loader 里会 redirect 到 c。
在浏览器的空白tab中访问a页面,然后点击link按钮跳转至 b 时,成功重定向至c页面,到此为止,都是正常的。
但此时点击后退,直接后退到了空白tab,即,历浏览器history记录中的a页面没了。
在c页面点击后退,应该后退至a页面。
问题出在 loader 的 redirect 逻辑中,
更进一步的说,是 router 前置钩子中next的逻辑的问题导致的。
client loader 执行时,如果有redirect,会调用next方法进行路由跳转的重定向,其中,next的参数传了redirect: true
问题正出在redirect选项上。
代码位置
可以看到,如果next的参数带有redirect:true
,router会中止当前跳转并重新发起一个replace。
拿刚才a b c 页面的例子带入一下,也就是说,原本 a -> b 的 push 操作被中止,然后重新发起一个 a -> c 的 replace。
这样一来,跳转完成之后,a 页面的历史记录确实就被替换了。这便是例子中问题的原因所在。
问题的核心在于路由前置钩子中next的逻辑。
经过分析,我发现next不应该有redirect参数。换句话说,redirect本身是没有push还是replace的选项的。
push和replace应该由原本的路由跳转所决定。
比如,还是刚才的例子,原始的跳转是 a -> b (push),那么redirect只是更换了target location而已,原始跳转是push,那么重新发起的路由跳转也是push。
如果原始的跳转是 a -> b (replace),而b 页面会redirect 到 c,那么重新发起的 a -> c 跳转也应该是 replace。
因为问题出在router 钩子逻辑中,而 next.js,remix 都没有router 钩子,所以不能参考。
shuvi-router 本身是参考vue-router的,所以这里看了一下vue的做法。
可以看到,vue-router中,重新发起route transition时,会保留当前的replace选项,并允许本次redirect进行覆盖。
代码位置
相比之下,这确实是一个比较好的策略。
默认情况下,redirect的push和replace由原本的路由跳转所决定。同时,redirect也可以覆盖设置。
例子:
在beforeEach钩子中进行重定向,并且把redirect方式覆盖为replace
router.beforeEach((to, from, next) => {
if (to.path === '/b') {
next({ name: 'c', replace: true })
}
next()
})
对标vue-router的策略,当路由前置钩子中通过next进行redirect时,保留原始的push/replace,并允许覆盖。
但是,因为shuvi这边承载 next 逻辑的 _doTransition
方法中,没有replace
参数,因此,为了能够判断原始的跳转方式,需要增加参数。
Let's come out with a checklist to make webpack 5 work.
Reference:
https://webpack.js.org/migrate/5/
https://github.com/nuxt/nuxt.js/pull/4616/files
vercel/next.js#13341
I got a project want to upgrade from rc37 to pre.10. In my memory there is a guide doc, could anyone give a hand?
For SSR, most of the time, user need to define their own custom API endpoint. Some of the example could be healthcheck or an API proxy. This could be anything. It is essential for us to implement this.
Other than that, user need to have custom header. This is for use case like CSP or caching purposes for each of our pages in SSR.
Refer to serverMiddleware by nuxt.js for more example.
For isomorphic use case, middleware can mean that a layer before entering our application/page. I think this can be done already with our navigation guard of router. #62 . But we can look more into this if there is a need to have a separate middleware for our application.
We can have a serverMiddleware in our config like nuxt.js which can apply a global middleware to all our pages or specific pages with path
specified.
Example:
shuvi.config.js
{
serverMiddleware: [
'auth', // global middleware (npm)
{ path: '/home', handler: 'api/home' } // route based middleware
]
}
api/home (middleware example)
interface MiddlewareContext {
req: Request,
res: Response,
next: Function
send: (result)=> void // if send is called the middleware exit and response, else continue render page
}
export default (context:MiddlewareContext) => {
context.res.setHeader('Custom', 'value')
if(condition){
context.send('end'); // you can modify result to any
return;
}
context.next();
}
context
can contain req
and res
. Might be better to make it support async await and not use (req, res, next)
.
Nextjs
Nuxtjs
在修复 #563 时,我发现e2e tests 里包含SSR时,相对路径的redirect。
一般来说,我们的功能应该是同构的,因为我也增加了CSR的对应e2e test,随后发现CSR时,相对路径的redirect无法正常工作。
具体来说。
SSR 相对路径的redirect 的test case,是正常的。假设我们有以下页面
/
/c
/x
,其loader会return redirect('c')
即相对路径redirect
/x/c
当SSR时,直接访问/x
,会302到/x/c
,相当于,此次redirect是基于/x
的。这是我们的当前预期。
然而,当前端路由跳转时,如,在/
页面,点击/x
的链接,结果却跳到了/c
页面,也就是说,此处redirect是基于跳转前的路径/
同时,当在SPA模式下,直接访问/x
,页面url会跳转至/x/c
,但是页面显示404。这里应该是另一个bug
也就是说,对于同一个页面,不同情况下的访问表现出截然不同的行为。
我认为,相对路径的redirect,是一个bad practice。
通常来说,前端路由导航由页面中的链接按钮触发,当点击链接导航时,可以是相对路径,并且是由跳转之前的url为base url。
也就是说,对于单纯的路由导航,其跳转地址可以是相对路径,并且规则很明确。
但是对于redirect,情况则不同了。
前端路由导航中下,redirect 包含三个对象:
如果redirect地址是一个相对路径,那么,这个是相对于navigate from,还是navigate to呢?我认为规则是不清晰的。
shuvi允许在loader中进行redirect。对于开发者来说,如果使用相对路径进行redirect,自然想到的是以loader所在的路由作为base。
但事实上,loader所在的路由是navigate to。
在上面的例子中(shuvi 的 e2e test中),SSR时访问/x
,redirect至 /x/c
,正是以 navigate to 作为base。
而前端路由跳转时,却redirect到 /c
,此时则变成了以 navigate from 作为base。vue-router 也是如此。
使用相对路径进行redirect时,vue 的 base 是navigate from
remix 和react-router 是基于 navigate to
next.js 待确认
相对来说,我倾向于以navigate to 作为base,比较符合直觉。
因为,无论是使用route config还是使用hook,还是loader来配置redirect。
redirect总是配置在navigate to上面的。
而navigate to是很明确的,所以这时如果有redirect,自然是应该基于当前的navigate to来计算实际路径。
另一方面,用户在跳转时,navigate from可以是任何地址。如果redirect的相对路径base是navigate from,那么最终地址也是五花八门的,是完全不可预料的,这样也就没有意义了。
It will be great to enable branch protection and show the CI status for all branches/PRs.
ref: https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/enabling-required-status-checks
related to PR #78
The defaultConfig
object has been mutated in deepmerge
function.
shuvi/packages/shuvi/src/api/api.ts
Line 91 in 15654fe
The defaultConfig
object should not be modified.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.