Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
CoCo_Code_Op2
next.js
提交
74771bc5
N
next.js
项目概览
CoCo_Code_Op2
/
next.js
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
N
next.js
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
74771bc5
编写于
5月 03, 2019
作者:
L
Luis Fernando Alvarez D
提交者:
GitHub
5月 03, 2019
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add support for /public (#7213)
上级
9d936f3a
变更
22
隐藏空白更改
内联
并排
Showing
22 changed file
with
165 addition
and
6 deletion
+165
-6
packages/next-server/lib/constants.ts
packages/next-server/lib/constants.ts
+1
-0
packages/next-server/server/lib/recursive-readdir-sync.ts
packages/next-server/server/lib/recursive-readdir-sync.ts
+25
-0
packages/next-server/server/next-server.ts
packages/next-server/server/next-server.ts
+37
-1
packages/next/export/index.js
packages/next/export/index.js
+18
-1
packages/next/server/next-dev-server.js
packages/next/server/next-dev-server.js
+13
-2
packages/next/taskfile-babel.js
packages/next/taskfile-babel.js
+3
-0
test/integration/basic/pages/about.js
test/integration/basic/pages/about.js
+3
-0
test/integration/basic/public/about
test/integration/basic/public/about
+1
-0
test/integration/basic/public/data/data.txt
test/integration/basic/public/data/data.txt
+1
-0
test/integration/basic/public/file
test/integration/basic/public/file
+1
-0
test/integration/basic/test/index.test.js
test/integration/basic/test/index.test.js
+2
-0
test/integration/basic/test/public-folder.js
test/integration/basic/test/public-folder.js
+19
-0
test/integration/export/public/about/data.txt
test/integration/export/public/about/data.txt
+1
-0
test/integration/export/public/query
test/integration/export/public/query
+1
-0
test/integration/export/static/data/item.txt
test/integration/export/static/data/item.txt
+1
-0
test/integration/export/test/index.test.js
test/integration/export/test/index.test.js
+1
-1
test/integration/export/test/ssr.js
test/integration/export/test/ssr.js
+15
-0
test/integration/production/public/about
test/integration/production/public/about
+1
-0
test/integration/production/public/data/data.txt
test/integration/production/public/data/data.txt
+1
-0
test/integration/production/public/file
test/integration/production/public/file
+1
-0
test/integration/production/test/index.test.js
test/integration/production/test/index.test.js
+13
-0
test/integration/production/test/security.js
test/integration/production/test/security.js
+6
-1
未找到文件。
packages/next-server/lib/constants.ts
浏览文件 @
74771bc5
...
...
@@ -13,6 +13,7 @@ export const BLOCKED_PAGES = [
'
/_document
'
,
'
/_app
'
,
]
export
const
CLIENT_PUBLIC_FILES_PATH
=
'
public
'
export
const
CLIENT_STATIC_FILES_PATH
=
'
static
'
export
const
CLIENT_STATIC_FILES_RUNTIME
=
'
runtime
'
export
const
CLIENT_STATIC_FILES_RUNTIME_PATH
=
`
${
CLIENT_STATIC_FILES_PATH
}
/
${
CLIENT_STATIC_FILES_RUNTIME
}
`
...
...
packages/next-server/server/lib/recursive-readdir-sync.ts
0 → 100644
浏览文件 @
74771bc5
import
fs
from
'
fs
'
import
{
join
}
from
'
path
'
/**
* Recursively read directory
* @param {string[]=[]} arr This doesn't have to be provided, it's used for the recursion
* @param {string=dir`} rootDir Used to replace the initial path, only the relative path is left, it's faster than path.relative.
* @returns Array holding all relative paths
*/
export
function
recursiveReadDirSync
(
dir
:
string
,
arr
:
string
[]
=
[],
rootDir
=
dir
):
string
[]
{
const
result
=
fs
.
readdirSync
(
dir
)
result
.
forEach
((
part
:
string
)
=>
{
const
absolutePath
=
join
(
dir
,
part
)
const
pathStat
=
fs
.
statSync
(
absolutePath
)
if
(
pathStat
.
isDirectory
())
{
recursiveReadDirSync
(
absolutePath
,
arr
,
rootDir
)
return
}
arr
.
push
(
absolutePath
.
replace
(
rootDir
,
''
))
})
return
arr
}
packages/next-server/server/next-server.ts
浏览文件 @
74771bc5
...
...
@@ -10,11 +10,15 @@ import { serveStatic } from './serve-static'
import
Router
,
{
route
,
Route
}
from
'
./router
'
import
{
isInternalUrl
,
isBlockedPage
}
from
'
./utils
'
import
loadConfig
from
'
./config
'
import
{
recursiveReadDirSync
}
from
'
./lib/recursive-readdir-sync
'
import
{
PHASE_PRODUCTION_SERVER
,
BUILD_ID_FILE
,
CLIENT_PUBLIC_FILES_PATH
,
CLIENT_STATIC_FILES_PATH
,
CLIENT_STATIC_FILES_RUNTIME
,
SERVER_DIRECTORY
,
PAGES_MANIFEST
,
}
from
'
../lib/constants
'
import
*
as
envConfig
from
'
../lib/runtime-config
'
import
{
loadComponents
}
from
'
./load-components
'
...
...
@@ -33,6 +37,7 @@ export default class Server {
quiet
:
boolean
nextConfig
:
NextConfig
distDir
:
string
publicDir
:
string
buildId
:
string
renderOpts
:
{
poweredByHeader
:
boolean
...
...
@@ -56,6 +61,8 @@ export default class Server {
const
phase
=
this
.
currentPhase
()
this
.
nextConfig
=
loadConfig
(
phase
,
this
.
dir
,
conf
)
this
.
distDir
=
join
(
this
.
dir
,
this
.
nextConfig
.
distDir
)
// this.pagesDir = join(this.dir, 'pages')
this
.
publicDir
=
join
(
this
.
dir
,
CLIENT_PUBLIC_FILES_PATH
)
// Only serverRuntimeConfig needs the default
// publicRuntimeConfig gets it's default in client/index.js
...
...
@@ -95,6 +102,7 @@ export default class Server {
const
routes
=
this
.
generateRoutes
()
this
.
router
=
new
Router
(
routes
)
this
.
setAssetPrefix
(
assetPrefix
)
}
...
...
@@ -193,6 +201,10 @@ export default class Server {
},
]
if
(
fs
.
existsSync
(
this
.
publicDir
))
{
routes
.
push
(...
this
.
generatePublicRoutes
())
}
if
(
this
.
nextConfig
.
useFileSystemPublicRoutes
)
{
// It's very important to keep this route's param optional.
// (but it should support as many params as needed, separated by '/')
...
...
@@ -214,6 +226,29 @@ export default class Server {
return
routes
}
private
generatePublicRoutes
():
Route
[]
{
const
routes
:
Route
[]
=
[]
const
publicFiles
=
recursiveReadDirSync
(
this
.
publicDir
)
const
serverBuildPath
=
join
(
this
.
distDir
,
SERVER_DIRECTORY
)
const
pagesManifest
=
require
(
join
(
serverBuildPath
,
PAGES_MANIFEST
))
publicFiles
.
forEach
((
path
)
=>
{
const
unixPath
=
path
.
replace
(
/
\\
/g
,
'
/
'
)
// Only include public files that will not replace a page path
if
(
!
pagesManifest
[
unixPath
])
{
routes
.
push
({
match
:
route
(
unixPath
),
fn
:
async
(
req
,
res
,
_params
,
parsedUrl
)
=>
{
const
p
=
join
(
this
.
publicDir
,
unixPath
)
await
this
.
serveStatic
(
req
,
res
,
p
,
parsedUrl
)
},
})
}
})
return
routes
}
private
async
run
(
req
:
IncomingMessage
,
res
:
ServerResponse
,
...
...
@@ -391,7 +426,8 @@ export default class Server {
const
resolved
=
resolve
(
path
)
if
(
resolved
.
indexOf
(
join
(
this
.
distDir
)
+
sep
)
!==
0
&&
resolved
.
indexOf
(
join
(
this
.
dir
,
'
static
'
)
+
sep
)
!==
0
resolved
.
indexOf
(
join
(
this
.
dir
,
'
static
'
)
+
sep
)
!==
0
&&
resolved
.
indexOf
(
join
(
this
.
dir
,
'
public
'
)
+
sep
)
!==
0
)
{
// Seems like the user is trying to traverse the filesystem.
return
false
...
...
packages/next/export/index.js
浏览文件 @
74771bc5
...
...
@@ -5,7 +5,7 @@ import mkdirpModule from 'mkdirp'
import
{
resolve
,
join
}
from
'
path
'
import
{
existsSync
,
readFileSync
}
from
'
fs
'
import
loadConfig
from
'
next-server/next-config
'
import
{
PHASE_EXPORT
,
SERVER_DIRECTORY
,
PAGES_MANIFEST
,
CONFIG_FILE
,
BUILD_ID_FILE
,
CLIENT_STATIC_FILES_PATH
}
from
'
next-server/constants
'
import
{
PHASE_EXPORT
,
SERVER_DIRECTORY
,
PAGES_MANIFEST
,
CONFIG_FILE
,
BUILD_ID_FILE
,
CLIENT_
PUBLIC_FILES_PATH
,
CLIENT_
STATIC_FILES_PATH
}
from
'
next-server/constants
'
import
createProgress
from
'
tty-aware-progress
'
import
{
promisify
}
from
'
util
'
import
{
recursiveDelete
}
from
'
../lib/recursive-delete
'
...
...
@@ -125,6 +125,23 @@ export default async function (dir, options, configuration) {
const
ampValidations
=
{}
let
hadValidationError
=
false
const
publicDir
=
join
(
dir
,
CLIENT_PUBLIC_FILES_PATH
)
// Copy public directory
if
(
existsSync
(
publicDir
))
{
log
(
'
copying "public" directory
'
)
await
cp
(
publicDir
,
outDir
,
{
expand
:
true
,
filter
(
path
)
{
// Exclude paths used by pages
return
!
exportPathMap
[
'
/
'
+
path
]
}
}
)
}
await
Promise
.
all
(
chunks
.
map
(
chunk
=>
...
...
packages/next/server/next-dev-server.js
浏览文件 @
74771bc5
...
...
@@ -112,6 +112,11 @@ export default class DevServer extends Server {
return
routes
}
// In development public files are not added to the router but handled as a fallback instead
generatePublicRoutes
()
{
return
[]
}
_filterAmpDevelopmentScript
(
html
,
event
)
{
if
(
event
.
code
!==
'
DISALLOWED_SCRIPT_TAG
'
)
{
return
true
...
...
@@ -145,8 +150,9 @@ export default class DevServer extends Server {
await
this
.
hotReloader
.
ensurePage
(
pathname
)
}
catch
(
err
)
{
if
(
err
.
code
===
'
ENOENT
'
)
{
res
.
statusCode
=
404
return
this
.
renderErrorToHTML
(
null
,
req
,
res
,
pathname
,
query
)
// Try to send a public file and let servePublic handle the request from here
await
this
.
servePublic
(
req
,
res
,
pathname
)
return
null
}
if
(
!
this
.
quiet
)
console
.
error
(
err
)
}
...
...
@@ -190,6 +196,11 @@ export default class DevServer extends Server {
res
.
setHeader
(
'
Cache-Control
'
,
'
no-store, must-revalidate
'
)
}
servePublic
(
req
,
res
,
path
)
{
const
p
=
join
(
this
.
publicDir
,
path
)
return
this
.
serveStatic
(
req
,
res
,
p
)
}
async
getCompilationError
(
page
)
{
const
errors
=
await
this
.
hotReloader
.
getCompilationErrors
(
page
)
if
(
errors
.
length
===
0
)
return
...
...
packages/next/taskfile-babel.js
浏览文件 @
74771bc5
...
...
@@ -17,6 +17,9 @@ module.exports = function (task) {
const
output
=
transform
(
file
.
data
,
options
)
const
ext
=
extname
(
file
.
base
)
// Include declaration files as they are
if
(
file
.
base
.
endsWith
(
'
.d.ts
'
))
return
// Replace `.ts|.tsx` with `.js` in files with an extension
if
(
ext
)
{
const
extRegex
=
new
RegExp
(
ext
.
replace
(
'
.
'
,
'
\\
.
'
)
+
'
$
'
,
'
i
'
)
...
...
test/integration/basic/pages/about.js
0 → 100644
浏览文件 @
74771bc5
export
default
()
=>
(
<
div
className
=
'
about-page
'
>
About
Page
<
/div
>
)
test/integration/basic/public/about
0 → 100644
浏览文件 @
74771bc5
about
\ No newline at end of file
test/integration/basic/public/data/data.txt
0 → 100644
浏览文件 @
74771bc5
data
\ No newline at end of file
test/integration/basic/public/file
0 → 100644
浏览文件 @
74771bc5
test
\ No newline at end of file
test/integration/basic/test/index.test.js
浏览文件 @
74771bc5
...
...
@@ -14,6 +14,7 @@ import errorRecovery from './error-recovery'
import
dynamic
from
'
./dynamic
'
import
processEnv
from
'
./process-env
'
import
typescript
from
'
./typescript
'
import
publicFolder
from
'
./public-folder
'
const
context
=
{}
jasmine
.
DEFAULT_TIMEOUT_INTERVAL
=
1000
*
60
*
5
...
...
@@ -40,4 +41,5 @@ describe('Basic Features', () => {
errorRecovery
(
context
,
(
p
,
q
)
=>
renderViaHTTP
(
context
.
appPort
,
p
,
q
))
typescript
(
context
,
(
p
,
q
)
=>
renderViaHTTP
(
context
.
appPort
,
p
,
q
))
processEnv
(
context
)
publicFolder
(
context
)
})
test/integration/basic/test/public-folder.js
0 → 100644
浏览文件 @
74771bc5
/* eslint-env jest */
import
{
renderViaHTTP
}
from
'
next-test-utils
'
export
default
(
context
)
=>
{
describe
(
'
Public folder
'
,
()
=>
{
it
(
'
should allow access to public files
'
,
async
()
=>
{
const
data
=
await
renderViaHTTP
(
context
.
appPort
,
'
/data/data.txt
'
)
expect
(
data
).
toBe
(
'
data
'
)
})
it
(
'
should prioritize pages over public files
'
,
async
()
=>
{
const
html
=
await
renderViaHTTP
(
context
.
appPort
,
'
/about
'
)
const
data
=
await
renderViaHTTP
(
context
.
appPort
,
'
/file
'
)
expect
(
html
).
toMatch
(
/About Page/
)
expect
(
data
).
toBe
(
'
test
'
)
})
})
}
test/integration/export/public/about/data.txt
0 → 100644
浏览文件 @
74771bc5
data
\ No newline at end of file
test/integration/export/public/query
0 → 100644
浏览文件 @
74771bc5
query
\ No newline at end of file
test/integration/export/static/data/item.txt
0 → 100644
浏览文件 @
74771bc5
item
\ No newline at end of file
test/integration/export/test/index.test.js
浏览文件 @
74771bc5
...
...
@@ -58,7 +58,7 @@ describe('Static Export', () => {
await
nextExport
(
appDir
,
{
outdir
:
outNoTrailSlash
})
nextConfig
.
restore
()
context
.
server
=
await
startStaticServer
(
join
(
appDir
,
'
out
'
)
)
context
.
server
=
await
startStaticServer
(
outdir
)
context
.
port
=
context
.
server
.
address
().
port
context
.
serverNoTrailSlash
=
await
startStaticServer
(
outNoTrailSlash
)
...
...
test/integration/export/test/ssr.js
浏览文件 @
74771bc5
...
...
@@ -61,5 +61,20 @@ export default function (context) {
// contains "404", so need to be specific here
expect
(
html
).
not
.
toMatch
(
/404.*page.*not.*found/i
)
})
it
(
'
Should serve static files
'
,
async
()
=>
{
const
data
=
await
renderViaHTTP
(
context
.
port
,
'
/static/data/item.txt
'
)
expect
(
data
).
toBe
(
'
item
'
)
})
it
(
'
Should serve public files and prioritize pages
'
,
async
()
=>
{
const
html
=
await
renderViaHTTP
(
context
.
port
,
'
/about
'
)
const
html2
=
await
renderViaHTTP
(
context
.
port
,
'
/query
'
)
const
data
=
await
renderViaHTTP
(
context
.
port
,
'
/about/data.txt
'
)
expect
(
html
).
toMatch
(
/This is the About page foobar/
)
expect
(
html2
).
toMatch
(
/{"a":"blue"}/
)
expect
(
data
).
toBe
(
'
data
'
)
})
})
}
test/integration/production/public/about
0 → 100644
浏览文件 @
74771bc5
about
\ No newline at end of file
test/integration/production/public/data/data.txt
0 → 100644
浏览文件 @
74771bc5
data
\ No newline at end of file
test/integration/production/public/file
0 → 100644
浏览文件 @
74771bc5
test
\ No newline at end of file
test/integration/production/test/index.test.js
浏览文件 @
74771bc5
...
...
@@ -268,6 +268,19 @@ describe('Production Usage', () => {
expect
(
data
).
toBe
(
'
item
'
)
})
it
(
'
Should allow access to public files
'
,
async
()
=>
{
const
data
=
await
renderViaHTTP
(
appPort
,
'
/data/data.txt
'
)
expect
(
data
).
toBe
(
'
data
'
)
})
it
(
'
Should prioritize pages over public files
'
,
async
()
=>
{
const
html
=
await
renderViaHTTP
(
appPort
,
'
/about
'
)
const
data
=
await
renderViaHTTP
(
appPort
,
'
/file
'
)
expect
(
html
).
toMatch
(
/About Page/
)
expect
(
data
).
toBe
(
'
test
'
)
})
it
(
'
should reload the page on page script error
'
,
async
()
=>
{
const
browser
=
await
webdriver
(
appPort
,
'
/counter
'
)
const
counter
=
await
browser
...
...
test/integration/production/test/security.js
浏览文件 @
74771bc5
...
...
@@ -30,7 +30,12 @@ module.exports = (context) => {
`/_next/:buildId/webpack/chunks/../../../info.json`
,
`/_next/:buildId/webpack/../../../info.json`
,
`/_next/../../../info.json`
,
`/static/../../../info.json`
`/static/../../../info.json`
,
`/static/../info.json`
,
`/../../../info.json`
,
`/../../info.json`
,
`/../info.json`
,
`/info.json`
]
for
(
const
path
of
pathsToCheck
)
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录