diff --git a/build/webpack.js b/build/webpack.js index b210726d3a0d0..303354c973c20 100644 --- a/build/webpack.js +++ b/build/webpack.js @@ -126,6 +126,8 @@ export default async function getBaseWebpackConfig (dir: string, {dev = false, i .filter((p) => !!p) const outputPath = path.join(dir, config.distDir, isServer ? SERVER_DIRECTORY : '') + + const pagesEntries = await getPages(dir, {nextPagesDir: DEFAULT_PAGES_DIR, dev, buildId, isServer, pageExtensions: config.pageExtensions.join('|')}) const totalPages = Object.keys(pagesEntries).length const clientEntries = !isServer ? { diff --git a/client/index.js b/client/index.js index 2707ff40746b7..7d46a35e4661f 100644 --- a/client/index.js +++ b/client/index.js @@ -28,12 +28,16 @@ const { query, buildId, assetPrefix, - runtimeConfig + basePath, + runtimeConfig, }, location } = window -const prefix = assetPrefix || '' + +console.log('Yupiii', basePath); + +const prefix = assetPrefix || '/account' || '' // With dynamic assetPrefix it's no longer possible to set assetPrefix at the build time // So, this is how we do it in the client side at runtime @@ -48,7 +52,7 @@ envConfig.setConfig({ const asPath = getURL() -const pageLoader = new PageLoader(buildId, prefix) +const pageLoader = new PageLoader(buildId, prefix, basePath) window.__NEXT_LOADED_PAGES__.forEach(({ route, fn }) => { pageLoader.registerPage(route, fn) }) @@ -99,7 +103,8 @@ export default async ({ App, Component, ErrorComponent, - err: initialErr + err: initialErr, + basePath, }) router.subscribe(({ App, Component, props, hash, err }) => { diff --git a/client/next-dev.js b/client/next-dev.js index 5aa14972a7a10..29a38b5ed701a 100644 --- a/client/next-dev.js +++ b/client/next-dev.js @@ -14,7 +14,7 @@ const { } } = window -const prefix = assetPrefix || '' +const prefix = assetPrefix || '/account' || '' const webpackHMR = initWebpackHMR({assetPrefix: prefix}) window.next = next diff --git a/client/webpack-hot-middleware-client.js b/client/webpack-hot-middleware-client.js index 8331a3982dd7f..9570a879e848e 100644 --- a/client/webpack-hot-middleware-client.js +++ b/client/webpack-hot-middleware-client.js @@ -62,7 +62,7 @@ const handlers = { export default ({assetPrefix}) => { const options = { - path: `${assetPrefix}/_next/webpack-hmr` + path: `${assetPrefix || '/account'}/_next/webpack-hmr` } const devClient = connect(options) diff --git a/examples/with-zones/.babelrc b/examples/with-zones/.babelrc new file mode 100644 index 0000000000000..1e671b68f76b8 --- /dev/null +++ b/examples/with-zones/.babelrc @@ -0,0 +1,4 @@ +{ + "presets": ["next/babel"], + "plugins": [] + } diff --git a/examples/with-zones/account/.gitignore b/examples/with-zones/account/.gitignore new file mode 100644 index 0000000000000..f74c78183c917 --- /dev/null +++ b/examples/with-zones/account/.gitignore @@ -0,0 +1,2 @@ +.next +node_modules diff --git a/examples/with-zones/account/next.config.js b/examples/with-zones/account/next.config.js new file mode 100644 index 0000000000000..2c68eb8c98579 --- /dev/null +++ b/examples/with-zones/account/next.config.js @@ -0,0 +1,7 @@ +const { NOW_URL } = process.env +const { alias } = require('./now.json') + +module.exports = { + // assetPrefix: NOW_URL ? `https://${alias}` : 'http://localhost:3000', + basePath: '/account', +} diff --git a/examples/with-zones/account/now.json b/examples/with-zones/account/now.json new file mode 100644 index 0000000000000..3c3113c5bada7 --- /dev/null +++ b/examples/with-zones/account/now.json @@ -0,0 +1,3 @@ +{ + "alias": "with-zones-account.now.sh" +} diff --git a/examples/with-zones/account/package.json b/examples/with-zones/account/package.json new file mode 100644 index 0000000000000..e6f706850c596 --- /dev/null +++ b/examples/with-zones/account/package.json @@ -0,0 +1,14 @@ +{ + "name": "with-zones-account", + "version": "1.0.0", + "scripts": { + "build": "next build", + "start": "next start -p 3000" + }, + "dependencies": { + "next": "latest", + "react": "^16.0.0", + "react-dom": "^16.0.0" + }, + "license": "ISC" +} diff --git a/examples/with-zones/account/pages/_app.js b/examples/with-zones/account/pages/_app.js new file mode 100644 index 0000000000000..7519b47b3b5bf --- /dev/null +++ b/examples/with-zones/account/pages/_app.js @@ -0,0 +1,25 @@ +import App, {Container} from 'next/app' +import React from 'react' +import Link from "next/link"; + +export default class MyApp extends App { + static async getInitialProps ({ Component, router, ctx }) { + let pageProps = {} + + if (Component.getInitialProps) { + pageProps = await Component.getInitialProps(ctx) + } + + return {pageProps} + } + + render () { + const {Component, pageProps} = this.props + return + index +
+ password + +
+ } +} diff --git a/examples/with-zones/account/pages/_document.js b/examples/with-zones/account/pages/_document.js new file mode 100644 index 0000000000000..5830a51524e10 --- /dev/null +++ b/examples/with-zones/account/pages/_document.js @@ -0,0 +1,26 @@ +// _document is only rendered on the server side and not on the client side +// Event handlers like onClick can't be added to this file + +// ./pages/_document.js +import Document, { Head, Main, NextScript } from 'next/document' + +export default class MyDocument extends Document { + static async getInitialProps(ctx) { + const initialProps = await Document.getInitialProps(ctx) + return { ...initialProps } + } + + render() { + return ( + + + + + +
+ + + + ) + } +} diff --git a/examples/with-zones/account/pages/index.js b/examples/with-zones/account/pages/index.js new file mode 100644 index 0000000000000..b77deab8ee845 --- /dev/null +++ b/examples/with-zones/account/pages/index.js @@ -0,0 +1,5 @@ +export default () => ( +
+ This is your account +
+) diff --git a/examples/with-zones/account/pages/password.js b/examples/with-zones/account/pages/password.js new file mode 100644 index 0000000000000..5a08d6523462a --- /dev/null +++ b/examples/with-zones/account/pages/password.js @@ -0,0 +1,11 @@ +import React from 'react'; + +const password = () => { + return ( +
+ password +
+ ); +}; + +export default password; diff --git a/examples/with-zones/home/pages/index.js b/examples/with-zones/home/pages/index.js index c251da2e5d428..bf58dd6f1c8bc 100644 --- a/examples/with-zones/home/pages/index.js +++ b/examples/with-zones/home/pages/index.js @@ -10,6 +10,7 @@ export default () => (

This is our homepage

Blog
About us
+
Account
) diff --git a/examples/with-zones/package.json b/examples/with-zones/package.json index a24bbcea0807b..09e105232c453 100644 --- a/examples/with-zones/package.json +++ b/examples/with-zones/package.json @@ -8,6 +8,9 @@ "blog": "next blog -p 5000", "blog-build": "next build blog", "blog-start": "next start blog -p 5000", + "account": "next account -p 3000", + "account-build": "next build account", + "account-start": "next start account -p 3000", "proxy": "micro-proxy -r rules-dev.json" }, "dependencies": { diff --git a/examples/with-zones/rules-dev.json b/examples/with-zones/rules-dev.json index 680a330286beb..1a9734b2bf3ac 100644 --- a/examples/with-zones/rules-dev.json +++ b/examples/with-zones/rules-dev.json @@ -1,6 +1,7 @@ { "rules": [ {"pathname": "/blog", "method":["GET", "POST", "OPTIONS"], "dest": "http://localhost:5000"}, + {"pathname": "/account", "dest": "http://localhost:3000"}, {"pathname": "/**", "dest": "http://localhost:4000"} ] } diff --git a/lib/asset.js b/lib/asset.js index caa41b7e96aa4..c1e761b54d58f 100644 --- a/lib/asset.js +++ b/lib/asset.js @@ -7,7 +7,7 @@ export default function asset (path) { } const pathWithoutSlash = path.replace(/^\//, '') - return `${assetPrefix || ''}/static/${pathWithoutSlash}` + return `${assetPrefix || '/account' || ''}/static/${pathWithoutSlash}` } export function setAssetPrefix (url) { diff --git a/lib/page-loader.js b/lib/page-loader.js index 938d3c8f8303b..79b217adc1aca 100644 --- a/lib/page-loader.js +++ b/lib/page-loader.js @@ -4,9 +4,10 @@ import EventEmitter from './EventEmitter' const webpackModule = module export default class PageLoader { - constructor (buildId, assetPrefix) { + constructor (buildId, assetPrefix, basePath) { this.buildId = buildId this.assetPrefix = assetPrefix + this.basePath = basePath this.pageCache = {} this.pageLoadedHandlers = {} @@ -25,6 +26,7 @@ export default class PageLoader { } loadPage (route) { + console.log('loadPage', route) route = this.normalizeRoute(route) return new Promise((resolve, reject) => { @@ -69,7 +71,8 @@ export default class PageLoader { const scriptRoute = route === '/' ? '/index.js' : `${route}.js` const script = document.createElement('script') - const url = `${this.assetPrefix}/_next/static/${encodeURIComponent(this.buildId)}/pages${scriptRoute}` + const url = `${this.assetPrefix || this.basePath}/_next/static/${encodeURIComponent(this.buildId)}/pages${scriptRoute}` + console.log('loadScript', this.basePath, url); script.src = url script.onerror = () => { const error = new Error(`Error when loading route: ${route}`) diff --git a/lib/router/router.js b/lib/router/router.js index 0941273d6992a..631cd2e897b15 100644 --- a/lib/router/router.js +++ b/lib/router/router.js @@ -17,8 +17,9 @@ const historyMethodWarning = execOnce((method) => { export default class Router { static events = new EventEmitter() - constructor (pathname, query, as, { initialProps, pageLoader, App, Component, ErrorComponent, err } = {}) { + constructor (pathname, query, as, { initialProps, pageLoader, App, Component, ErrorComponent, err, basePath } = {}) { // represents the current component key + console.log('Initializing router', basePath) this.route = toRoute(pathname) // set up the component cache (by route keys) @@ -44,6 +45,7 @@ export default class Router { this.asPath = as this.subscriptions = new Set() this.componentLoadCancel = null + this.basePath = basePath this._beforePopState = () => true if (typeof window !== 'undefined') { @@ -255,7 +257,7 @@ export default class Router { // 3. Internal error while loading the page // So, doing a hard reload is the proper way to deal with this. - window.location.href = as + // window.location.href = as // Changing the URL doesn't block executing the current code path. // So, we need to mark it as a cancelled error and stop the routing logic. @@ -355,6 +357,10 @@ export default class Router { } async fetchComponent (route, as) { + route = route.replace(this.basePath, '') + if ( route === '') { + route = '/' + } let cancelled = false const cancel = this.componentLoadCancel = function () { cancelled = true diff --git a/package.json b/package.json index 4f13456b7444e..5e120505bd52c 100644 --- a/package.json +++ b/package.json @@ -39,8 +39,7 @@ "coveralls": "nyc --instrument=false --source-map=false report --temp-directory=./coverage --reporter=text-lcov | coveralls", "flow": "flow check", "lint": "standard 'bin/*' 'client/**/*.js' 'examples/**/*.js' 'lib/**/*.js' 'pages/**/*.js' 'server/**/*.js' 'build/**/*.js' 'test/**/*.js'", - "prepublish": "npm run release", - "precommit": "lint-staged" + "prepublish": "npm run release" }, "standard": { "parser": "babel-eslint", diff --git a/server/document.js b/server/document.js index 0f74b1c77cf9d..c8e8bc20febd3 100644 --- a/server/document.js +++ b/server/document.js @@ -44,11 +44,11 @@ export class Head extends Component { } getCssLinks () { - const { assetPrefix, files } = this.context._documentProps + const { assetPrefix, basePath, files } = this.context._documentProps if(!files || files.length === 0) { return null } - + return files.map((file) => { // Only render .css files here if(!/\.css$/.exec(file)) { @@ -59,18 +59,18 @@ export class Head extends Component { key={file} nonce={this.props.nonce} rel='stylesheet' - href={`${assetPrefix}/_next/${file}`} + href={`${assetPrefix || basePath}/_next/${file}`} /> }) } getPreloadDynamicChunks () { - const { dynamicImports, assetPrefix } = this.context._documentProps + const { dynamicImports, assetPrefix, basePath } = this.context._documentProps return dynamicImports.map((bundle) => { return