mirror of
https://github.com/wasp-lang/wasp.git
synced 2024-12-27 19:14:52 +03:00
Adds support for client subdir (#1516)
This commit is contained in:
parent
9f31b3229e
commit
520c35af5c
@ -1,5 +1,22 @@
|
||||
# Changelog
|
||||
|
||||
## 0.11.8
|
||||
|
||||
### 🎉 [New Feature] Serving the Client From a Subdirectory
|
||||
|
||||
You can now serve the client from a subdirectory. This is useful if you want to serve the client from a subdirectory of your domain, e.g. `https://example.com/my-app/`.
|
||||
|
||||
To do this, you need to add the `client.baseDir` property to your `.wasp` file:
|
||||
|
||||
```wasp
|
||||
app todoApp {
|
||||
// ...
|
||||
client: {
|
||||
baseDir: "/my-app",
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## 0.11.7
|
||||
|
||||
### 🐞 Bug fixes / 🔧 small improvements
|
||||
|
@ -47,7 +47,7 @@ export const routes = {
|
||||
export type Routes = RouteDefinitionsToRoutes<typeof routes>
|
||||
|
||||
const router = (
|
||||
<Router>
|
||||
<Router basename="{= baseDir =}">
|
||||
{=# rootComponent.isDefined =}
|
||||
<{= rootComponent.importIdentifier =}>
|
||||
{=/ rootComponent.isDefined =}
|
||||
|
@ -12,9 +12,10 @@ const _waspUserProvidedConfig = {};
|
||||
{=/ customViteConfig.isDefined =}
|
||||
|
||||
const defaultViteConfig = {
|
||||
base: "{= baseDir =}",
|
||||
plugins: [react()],
|
||||
server: {
|
||||
port: 3000,
|
||||
port: {= defaultClientPort =},
|
||||
host: "0.0.0.0",
|
||||
open: true,
|
||||
},
|
||||
|
@ -32,7 +32,7 @@ const resolvedConfig = merge(config.all, config[env])
|
||||
export default resolvedConfig
|
||||
|
||||
function getDevelopmentConfig() {
|
||||
const frontendUrl = stripTrailingSlash(process.env.WASP_WEB_CLIENT_URL) || 'http://localhost:3000';
|
||||
const frontendUrl = stripTrailingSlash(process.env.WASP_WEB_CLIENT_URL || '{= defaultClientUrl =}');
|
||||
return {
|
||||
frontendUrl,
|
||||
allowedCORSOrigins: '*',
|
||||
|
@ -109,7 +109,7 @@
|
||||
"file",
|
||||
"server/src/config.js"
|
||||
],
|
||||
"85e22f3e8e87902ed0b58a3e529d9c2167b553383f33fbb4261a5031a3c5ba27"
|
||||
"d135535e045e5f5852e0b6d8bd49360e7231021cd38b540f419f5f44c6158dc2"
|
||||
],
|
||||
[
|
||||
[
|
||||
@ -459,7 +459,7 @@
|
||||
"file",
|
||||
"web-app/src/router.tsx"
|
||||
],
|
||||
"79192ef1e636c2573815ca7151cf8e3a76ebb00a0b0ee3e804cbb60cba5f7197"
|
||||
"067478c4990bbe966fa1984cd9db91aba9aaa68196c5858eab787eb376ab48b9"
|
||||
],
|
||||
[
|
||||
[
|
||||
@ -564,6 +564,6 @@
|
||||
"file",
|
||||
"web-app/vite.config.ts"
|
||||
],
|
||||
"ba22ae0b9027a2a4d3cd2689e9a9e1caff526b96dfab5e7f0f58f194dff830d9"
|
||||
"08962d79f2d71eb470ee85dee03db6deca7ede28df9d41542bbaea752db0eeed"
|
||||
]
|
||||
]
|
@ -26,7 +26,7 @@ const resolvedConfig = merge(config.all, config[env])
|
||||
export default resolvedConfig
|
||||
|
||||
function getDevelopmentConfig() {
|
||||
const frontendUrl = stripTrailingSlash(process.env.WASP_WEB_CLIENT_URL) || 'http://localhost:3000';
|
||||
const frontendUrl = stripTrailingSlash(process.env.WASP_WEB_CLIENT_URL || 'http://localhost:3000/');
|
||||
return {
|
||||
frontendUrl,
|
||||
allowedCORSOrigins: '*',
|
||||
|
@ -24,7 +24,7 @@ export const routes = {
|
||||
export type Routes = RouteDefinitionsToRoutes<typeof routes>
|
||||
|
||||
const router = (
|
||||
<Router>
|
||||
<Router basename="/">
|
||||
<Switch>
|
||||
{Object.entries(routes).map(([routeKey, route]) => (
|
||||
<Route
|
||||
|
@ -6,6 +6,7 @@ import customViteConfig from './src/ext-src/vite.config'
|
||||
const _waspUserProvidedConfig = customViteConfig
|
||||
|
||||
const defaultViteConfig = {
|
||||
base: "/",
|
||||
plugins: [react()],
|
||||
server: {
|
||||
port: 3000,
|
||||
|
@ -116,7 +116,7 @@
|
||||
"file",
|
||||
"server/src/config.js"
|
||||
],
|
||||
"85e22f3e8e87902ed0b58a3e529d9c2167b553383f33fbb4261a5031a3c5ba27"
|
||||
"d135535e045e5f5852e0b6d8bd49360e7231021cd38b540f419f5f44c6158dc2"
|
||||
],
|
||||
[
|
||||
[
|
||||
@ -473,7 +473,7 @@
|
||||
"file",
|
||||
"web-app/src/router.tsx"
|
||||
],
|
||||
"79192ef1e636c2573815ca7151cf8e3a76ebb00a0b0ee3e804cbb60cba5f7197"
|
||||
"067478c4990bbe966fa1984cd9db91aba9aaa68196c5858eab787eb376ab48b9"
|
||||
],
|
||||
[
|
||||
[
|
||||
@ -578,6 +578,6 @@
|
||||
"file",
|
||||
"web-app/vite.config.ts"
|
||||
],
|
||||
"ba22ae0b9027a2a4d3cd2689e9a9e1caff526b96dfab5e7f0f58f194dff830d9"
|
||||
"08962d79f2d71eb470ee85dee03db6deca7ede28df9d41542bbaea752db0eeed"
|
||||
]
|
||||
]
|
@ -26,7 +26,7 @@ const resolvedConfig = merge(config.all, config[env])
|
||||
export default resolvedConfig
|
||||
|
||||
function getDevelopmentConfig() {
|
||||
const frontendUrl = stripTrailingSlash(process.env.WASP_WEB_CLIENT_URL) || 'http://localhost:3000';
|
||||
const frontendUrl = stripTrailingSlash(process.env.WASP_WEB_CLIENT_URL || 'http://localhost:3000/');
|
||||
return {
|
||||
frontendUrl,
|
||||
allowedCORSOrigins: '*',
|
||||
|
@ -24,7 +24,7 @@ export const routes = {
|
||||
export type Routes = RouteDefinitionsToRoutes<typeof routes>
|
||||
|
||||
const router = (
|
||||
<Router>
|
||||
<Router basename="/">
|
||||
<Switch>
|
||||
{Object.entries(routes).map(([routeKey, route]) => (
|
||||
<Route
|
||||
|
@ -6,6 +6,7 @@ import customViteConfig from './src/ext-src/vite.config'
|
||||
const _waspUserProvidedConfig = customViteConfig
|
||||
|
||||
const defaultViteConfig = {
|
||||
base: "/",
|
||||
plugins: [react()],
|
||||
server: {
|
||||
port: 3000,
|
||||
|
@ -193,7 +193,7 @@
|
||||
"file",
|
||||
"server/src/config.js"
|
||||
],
|
||||
"b5e2d31201460b018e781532b7bb6348cf3f7eb45851a81711a18584c0f4f5ac"
|
||||
"e4b647166ce3a74d1260f3505ce6366b52d195d6d1dcb75929b3fef30ea9ea4d"
|
||||
],
|
||||
[
|
||||
[
|
||||
@ -914,7 +914,7 @@
|
||||
"file",
|
||||
"web-app/src/router.tsx"
|
||||
],
|
||||
"1b167573635d206d53a8598ae39a81b140cd017c6c71ce13bf57c9a04b5b8160"
|
||||
"16209b667488c40c3a7a80be224d6d1ebb8df75bbaf8f2c6398eff07a92618ca"
|
||||
],
|
||||
[
|
||||
[
|
||||
@ -1026,6 +1026,6 @@
|
||||
"file",
|
||||
"web-app/vite.config.ts"
|
||||
],
|
||||
"ba22ae0b9027a2a4d3cd2689e9a9e1caff526b96dfab5e7f0f58f194dff830d9"
|
||||
"08962d79f2d71eb470ee85dee03db6deca7ede28df9d41542bbaea752db0eeed"
|
||||
]
|
||||
]
|
@ -29,7 +29,7 @@ const resolvedConfig = merge(config.all, config[env])
|
||||
export default resolvedConfig
|
||||
|
||||
function getDevelopmentConfig() {
|
||||
const frontendUrl = stripTrailingSlash(process.env.WASP_WEB_CLIENT_URL) || 'http://localhost:3000';
|
||||
const frontendUrl = stripTrailingSlash(process.env.WASP_WEB_CLIENT_URL || 'http://localhost:3000/');
|
||||
return {
|
||||
frontendUrl,
|
||||
allowedCORSOrigins: '*',
|
||||
|
@ -27,7 +27,7 @@ export const routes = {
|
||||
export type Routes = RouteDefinitionsToRoutes<typeof routes>
|
||||
|
||||
const router = (
|
||||
<Router>
|
||||
<Router basename="/">
|
||||
<App>
|
||||
<Switch>
|
||||
{Object.entries(routes).map(([routeKey, route]) => (
|
||||
|
@ -6,6 +6,7 @@ import customViteConfig from './src/ext-src/vite.config'
|
||||
const _waspUserProvidedConfig = customViteConfig
|
||||
|
||||
const defaultViteConfig = {
|
||||
base: "/",
|
||||
plugins: [react()],
|
||||
server: {
|
||||
port: 3000,
|
||||
|
@ -116,7 +116,7 @@
|
||||
"file",
|
||||
"server/src/config.js"
|
||||
],
|
||||
"85e22f3e8e87902ed0b58a3e529d9c2167b553383f33fbb4261a5031a3c5ba27"
|
||||
"d135535e045e5f5852e0b6d8bd49360e7231021cd38b540f419f5f44c6158dc2"
|
||||
],
|
||||
[
|
||||
[
|
||||
@ -515,7 +515,7 @@
|
||||
"file",
|
||||
"web-app/src/router.tsx"
|
||||
],
|
||||
"79192ef1e636c2573815ca7151cf8e3a76ebb00a0b0ee3e804cbb60cba5f7197"
|
||||
"067478c4990bbe966fa1984cd9db91aba9aaa68196c5858eab787eb376ab48b9"
|
||||
],
|
||||
[
|
||||
[
|
||||
@ -620,6 +620,6 @@
|
||||
"file",
|
||||
"web-app/vite.config.ts"
|
||||
],
|
||||
"ba22ae0b9027a2a4d3cd2689e9a9e1caff526b96dfab5e7f0f58f194dff830d9"
|
||||
"08962d79f2d71eb470ee85dee03db6deca7ede28df9d41542bbaea752db0eeed"
|
||||
]
|
||||
]
|
@ -26,7 +26,7 @@ const resolvedConfig = merge(config.all, config[env])
|
||||
export default resolvedConfig
|
||||
|
||||
function getDevelopmentConfig() {
|
||||
const frontendUrl = stripTrailingSlash(process.env.WASP_WEB_CLIENT_URL) || 'http://localhost:3000';
|
||||
const frontendUrl = stripTrailingSlash(process.env.WASP_WEB_CLIENT_URL || 'http://localhost:3000/');
|
||||
return {
|
||||
frontendUrl,
|
||||
allowedCORSOrigins: '*',
|
||||
|
@ -24,7 +24,7 @@ export const routes = {
|
||||
export type Routes = RouteDefinitionsToRoutes<typeof routes>
|
||||
|
||||
const router = (
|
||||
<Router>
|
||||
<Router basename="/">
|
||||
<Switch>
|
||||
{Object.entries(routes).map(([routeKey, route]) => (
|
||||
<Route
|
||||
|
@ -6,6 +6,7 @@ import customViteConfig from './src/ext-src/vite.config'
|
||||
const _waspUserProvidedConfig = customViteConfig
|
||||
|
||||
const defaultViteConfig = {
|
||||
base: "/",
|
||||
plugins: [react()],
|
||||
server: {
|
||||
port: 3000,
|
||||
|
@ -116,7 +116,7 @@
|
||||
"file",
|
||||
"server/src/config.js"
|
||||
],
|
||||
"85e22f3e8e87902ed0b58a3e529d9c2167b553383f33fbb4261a5031a3c5ba27"
|
||||
"d135535e045e5f5852e0b6d8bd49360e7231021cd38b540f419f5f44c6158dc2"
|
||||
],
|
||||
[
|
||||
[
|
||||
@ -473,7 +473,7 @@
|
||||
"file",
|
||||
"web-app/src/router.tsx"
|
||||
],
|
||||
"79192ef1e636c2573815ca7151cf8e3a76ebb00a0b0ee3e804cbb60cba5f7197"
|
||||
"067478c4990bbe966fa1984cd9db91aba9aaa68196c5858eab787eb376ab48b9"
|
||||
],
|
||||
[
|
||||
[
|
||||
@ -578,6 +578,6 @@
|
||||
"file",
|
||||
"web-app/vite.config.ts"
|
||||
],
|
||||
"ba22ae0b9027a2a4d3cd2689e9a9e1caff526b96dfab5e7f0f58f194dff830d9"
|
||||
"08962d79f2d71eb470ee85dee03db6deca7ede28df9d41542bbaea752db0eeed"
|
||||
]
|
||||
]
|
@ -26,7 +26,7 @@ const resolvedConfig = merge(config.all, config[env])
|
||||
export default resolvedConfig
|
||||
|
||||
function getDevelopmentConfig() {
|
||||
const frontendUrl = stripTrailingSlash(process.env.WASP_WEB_CLIENT_URL) || 'http://localhost:3000';
|
||||
const frontendUrl = stripTrailingSlash(process.env.WASP_WEB_CLIENT_URL || 'http://localhost:3000/');
|
||||
return {
|
||||
frontendUrl,
|
||||
allowedCORSOrigins: '*',
|
||||
|
@ -24,7 +24,7 @@ export const routes = {
|
||||
export type Routes = RouteDefinitionsToRoutes<typeof routes>
|
||||
|
||||
const router = (
|
||||
<Router>
|
||||
<Router basename="/">
|
||||
<Switch>
|
||||
{Object.entries(routes).map(([routeKey, route]) => (
|
||||
<Route
|
||||
|
@ -6,6 +6,7 @@ import customViteConfig from './src/ext-src/vite.config'
|
||||
const _waspUserProvidedConfig = customViteConfig
|
||||
|
||||
const defaultViteConfig = {
|
||||
base: "/",
|
||||
plugins: [react()],
|
||||
server: {
|
||||
port: 3000,
|
||||
|
@ -10,6 +10,8 @@ import Wasp.AppSpec.ExtImport (ExtImport)
|
||||
|
||||
data Client = Client
|
||||
{ setupFn :: Maybe ExtImport,
|
||||
rootComponent :: Maybe ExtImport
|
||||
rootComponent :: Maybe ExtImport,
|
||||
-- We expect the base dir to start with a slash e.g. /client
|
||||
baseDir :: Maybe String
|
||||
}
|
||||
deriving (Show, Eq, Data)
|
||||
|
@ -23,6 +23,7 @@ import Wasp.AppSpec.App (App)
|
||||
import qualified Wasp.AppSpec.App as AS.App
|
||||
import qualified Wasp.AppSpec.App as App
|
||||
import qualified Wasp.AppSpec.App.Auth as Auth
|
||||
import qualified Wasp.AppSpec.App.Client as Client
|
||||
import qualified Wasp.AppSpec.App.Db as AS.Db
|
||||
import qualified Wasp.AppSpec.App.Wasp as Wasp
|
||||
import Wasp.AppSpec.Core.Decl (takeDecls)
|
||||
@ -61,7 +62,8 @@ validateAppSpec spec =
|
||||
validateApiRoutesAreUnique spec,
|
||||
validateApiNamespacePathsAreUnique spec,
|
||||
validateCrudOperations spec,
|
||||
validatePrismaOptions spec
|
||||
validatePrismaOptions spec,
|
||||
validateWebAppBaseDir spec
|
||||
]
|
||||
|
||||
validateExactlyOneAppExists :: AppSpec -> Maybe ValidationError
|
||||
@ -364,6 +366,19 @@ validatePrismaOptions spec =
|
||||
prismaClientPreviewFeatures = AS.Db.clientPreviewFeatures =<< prismaOptions
|
||||
prismaDbExtensions = AS.Db.dbExtensions =<< prismaOptions
|
||||
|
||||
validateWebAppBaseDir :: AppSpec -> [ValidationError]
|
||||
validateWebAppBaseDir spec = case maybeBaseDir of
|
||||
Just baseDir
|
||||
| not (startsWithSlash baseDir) ->
|
||||
[GenericValidationError "The app.client.baseDir should start with a slash e.g. \"/test\""]
|
||||
_anyOtherCase -> []
|
||||
where
|
||||
maybeBaseDir = Client.baseDir =<< AS.App.client (snd $ getApp spec)
|
||||
|
||||
startsWithSlash :: String -> Bool
|
||||
startsWithSlash ('/' : _) = True
|
||||
startsWithSlash _ = False
|
||||
|
||||
-- | This function assumes that @AppSpec@ it operates on was validated beforehand (with @validateAppSpec@ function).
|
||||
-- TODO: It would be great if we could ensure this at type level, but we decided that was too much work for now.
|
||||
-- Check https://github.com/wasp-lang/wasp/pull/455 for considerations on this and analysis of different approaches.
|
||||
|
@ -1,6 +1,5 @@
|
||||
module Wasp.Generator.ServerGenerator.ConfigG
|
||||
( genConfigFile,
|
||||
configFileInSrcDir,
|
||||
)
|
||||
where
|
||||
|
||||
@ -12,6 +11,7 @@ import Wasp.AppSpec.Valid (isAuthEnabled)
|
||||
import Wasp.Generator.FileDraft (FileDraft)
|
||||
import Wasp.Generator.Monad (Generator)
|
||||
import qualified Wasp.Generator.ServerGenerator.Common as C
|
||||
import qualified Wasp.Generator.WebAppGenerator.Common as WebApp
|
||||
import Wasp.Project.Db (databaseUrlEnvVarName)
|
||||
|
||||
genConfigFile :: AppSpec -> Generator FileDraft
|
||||
@ -22,7 +22,8 @@ genConfigFile spec = return $ C.mkTmplFdWithDstAndData tmplFile dstFile (Just tm
|
||||
tmplData =
|
||||
object
|
||||
[ "isAuthEnabled" .= isAuthEnabled spec,
|
||||
"databaseUrlEnvVarName" .= databaseUrlEnvVarName
|
||||
"databaseUrlEnvVarName" .= databaseUrlEnvVarName,
|
||||
"defaultClientUrl" .= WebApp.getDefaultClientUrl spec
|
||||
]
|
||||
|
||||
configFileInSrcDir :: Path' (Rel C.ServerSrcDir) File'
|
||||
|
@ -339,7 +339,11 @@ genViteConfig spec = return $ C.mkTmplFdWithData tmplFile tmplData
|
||||
where
|
||||
tmplFile = C.asTmplFile [relfile|vite.config.ts|]
|
||||
tmplData =
|
||||
object ["customViteConfig" .= jsImportToImportJson (makeCustomViteConfigJsImport <$> AS.customViteConfigPath spec)]
|
||||
object
|
||||
[ "customViteConfig" .= jsImportToImportJson (makeCustomViteConfigJsImport <$> AS.customViteConfigPath spec),
|
||||
"baseDir" .= SP.fromAbsDirP (C.getBaseDir spec),
|
||||
"defaultClientPort" .= C.defaultClientPort
|
||||
]
|
||||
|
||||
makeCustomViteConfigJsImport :: Path' (Rel SourceExternalCodeDir) File' -> JsImport
|
||||
makeCustomViteConfigJsImport pathToConfig = makeJsImport importPath importName
|
||||
|
@ -20,14 +20,21 @@ module Wasp.Generator.WebAppGenerator.Common
|
||||
toViteImportPath,
|
||||
staticAssetsDirInWebAppDir,
|
||||
WebAppStaticAssetsDir,
|
||||
getBaseDir,
|
||||
getDefaultClientUrl,
|
||||
defaultClientPort,
|
||||
)
|
||||
where
|
||||
|
||||
import qualified Data.Aeson as Aeson
|
||||
import Data.Maybe (fromJust)
|
||||
import StrongPath (Dir, File, File', Path, Path', Posix, Rel, reldir, (</>))
|
||||
import Data.Maybe (fromJust, fromMaybe)
|
||||
import StrongPath (Abs, Dir, File, File', Path, Path', Posix, Rel, absdirP, reldir, (</>))
|
||||
import qualified StrongPath as SP
|
||||
import System.FilePath (splitExtension)
|
||||
import Wasp.AppSpec (AppSpec)
|
||||
import qualified Wasp.AppSpec.App as AS.App
|
||||
import qualified Wasp.AppSpec.App.Client as AS.App.Client
|
||||
import Wasp.AppSpec.Valid (getApp)
|
||||
import Wasp.Generator.Common
|
||||
( GeneratedSrcDir,
|
||||
ProjectRootDir,
|
||||
@ -123,3 +130,14 @@ toViteImportPath :: Path Posix (Rel r) (File f) -> Path Posix (Rel r) (File f)
|
||||
toViteImportPath = fromJust . SP.parseRelFileP . dropExtension . SP.fromRelFileP
|
||||
where
|
||||
dropExtension = fst . splitExtension
|
||||
|
||||
getBaseDir :: AppSpec -> Path Posix Abs (Dir ())
|
||||
getBaseDir spec = fromMaybe [absdirP|/|] maybeBaseDir
|
||||
where
|
||||
maybeBaseDir = SP.parseAbsDirP =<< (AS.App.Client.baseDir =<< AS.App.client (snd $ getApp spec))
|
||||
|
||||
defaultClientPort :: Int
|
||||
defaultClientPort = 3000
|
||||
|
||||
getDefaultClientUrl :: AppSpec -> String
|
||||
getDefaultClientUrl spec = "http://localhost:" ++ show defaultClientPort ++ SP.fromAbsDirP (getBaseDir spec)
|
||||
|
@ -10,6 +10,7 @@ import qualified Data.Aeson as Aeson
|
||||
import Data.List (find)
|
||||
import Data.Maybe (fromMaybe)
|
||||
import StrongPath (Dir, Path, Rel, reldir, reldirP, relfile, (</>))
|
||||
import qualified StrongPath as SP
|
||||
import StrongPath.Types (Posix)
|
||||
import Wasp.AppSpec (AppSpec)
|
||||
import qualified Wasp.AppSpec as AS
|
||||
@ -36,7 +37,8 @@ data RouterTemplateData = RouterTemplateData
|
||||
_isAuthEnabled :: Bool,
|
||||
_isExternalAuthEnabled :: Bool,
|
||||
_externalAuthProviders :: ![ExternalAuthProviderTemplateData],
|
||||
_rootComponent :: Aeson.Value
|
||||
_rootComponent :: Aeson.Value,
|
||||
_baseDir :: String
|
||||
}
|
||||
|
||||
instance ToJSON RouterTemplateData where
|
||||
@ -47,7 +49,8 @@ instance ToJSON RouterTemplateData where
|
||||
"isAuthEnabled" .= _isAuthEnabled routerTD,
|
||||
"isExternalAuthEnabled" .= _isExternalAuthEnabled routerTD,
|
||||
"externalAuthProviders" .= _externalAuthProviders routerTD,
|
||||
"rootComponent" .= _rootComponent routerTD
|
||||
"rootComponent" .= _rootComponent routerTD,
|
||||
"baseDir" .= _baseDir routerTD
|
||||
]
|
||||
|
||||
data RouteTemplateData = RouteTemplateData
|
||||
@ -124,7 +127,8 @@ createRouterTemplateData spec =
|
||||
_isAuthEnabled = isAuthEnabled spec,
|
||||
_isExternalAuthEnabled = (AS.App.Auth.isExternalAuthEnabled <$> maybeAuth) == Just True,
|
||||
_externalAuthProviders = externalAuthProviders,
|
||||
_rootComponent = extImportToImportJson relPathToWebAppSrcDir maybeRootComponent
|
||||
_rootComponent = extImportToImportJson relPathToWebAppSrcDir maybeRootComponent,
|
||||
_baseDir = SP.fromAbsDirP $ C.getBaseDir spec
|
||||
}
|
||||
where
|
||||
routes = map (createRouteTemplateData spec) $ AS.getRoutes spec
|
||||
|
@ -62,7 +62,8 @@ spec_Analyzer = do
|
||||
" },",
|
||||
" client: {",
|
||||
" rootComponent: import { App } from \"@client/App.jsx\",",
|
||||
" setupFn: import { setupClient } from \"@client/baz.js\"",
|
||||
" setupFn: import { setupClient } from \"@client/baz.js\",",
|
||||
" baseDir: \"/\"",
|
||||
" },",
|
||||
" db: {",
|
||||
" system: PostgreSQL,",
|
||||
@ -176,7 +177,8 @@ spec_Analyzer = do
|
||||
ExtImport (ExtImportField "setupClient") (fromJust $ SP.parseRelFileP "baz.js"),
|
||||
Client.rootComponent =
|
||||
Just $
|
||||
ExtImport (ExtImportField "App") (fromJust $ SP.parseRelFileP "App.jsx")
|
||||
ExtImport (ExtImportField "App") (fromJust $ SP.parseRelFileP "App.jsx"),
|
||||
Client.baseDir = Just "/"
|
||||
},
|
||||
App.db =
|
||||
Just
|
||||
|
6
web/docs/project/_baseDirEnvNote.md
Normal file
6
web/docs/project/_baseDirEnvNote.md
Normal file
@ -0,0 +1,6 @@
|
||||
:::caution Setting the correct env variable
|
||||
|
||||
If you set the `baseDir` option, make sure that the `WASP_WEB_CLIENT_URL` env variable also includes that base directory.
|
||||
|
||||
For example, if you are serving your app from `https://example.com/my-app`, the `WASP_WEB_CLIENT_URL` should be also set to `https://example.com/my-app`, and not just `https://example.com`.
|
||||
:::
|
@ -2,6 +2,8 @@
|
||||
title: Client Config
|
||||
---
|
||||
|
||||
import BaseDirEnvNote from './_baseDirEnvNote.md'
|
||||
|
||||
import { ShowForTs, ShowForJs } from '@site/src/components/TsJsHelpers'
|
||||
|
||||
You can configure the client using the `client` field inside the `app` declaration:
|
||||
@ -265,6 +267,26 @@ explained in
|
||||
|
||||
Read more about the setup function in the [API Reference](#setupfn-clientimport).
|
||||
|
||||
## Base Directory
|
||||
|
||||
If you need to serve the client from a subdirectory, you can use the `baseDir` option:
|
||||
|
||||
```wasp title="main.wasp"
|
||||
app MyApp {
|
||||
title: "My app",
|
||||
// ...
|
||||
client: {
|
||||
baseDir: "/my-app",
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This means that if you serve your app from `https://example.com/my-app`, the
|
||||
router will work correctly, and all the assets will be served from
|
||||
`https://example.com/my-app`.
|
||||
|
||||
<BaseDirEnvNote />
|
||||
|
||||
## API Reference
|
||||
|
||||
<Tabs groupId="js-ts">
|
||||
@ -290,7 +312,8 @@ app MyApp {
|
||||
// ...
|
||||
client: {
|
||||
rootComponent: import Root from "@client/Root.tsx",
|
||||
setupFn: import mySetupFunction from "@client/myClientSetupCode.ts"
|
||||
setupFn: import mySetupFunction from "@client/myClientSetupCode.ts",
|
||||
baseDir: "/my-app",
|
||||
}
|
||||
}
|
||||
```
|
||||
@ -413,3 +436,14 @@ Client has the following options:
|
||||
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
- #### `baseDir: String`
|
||||
|
||||
If you need to serve the client from a subdirectory, you can use the `baseDir` option.
|
||||
|
||||
If you set `baseDir` to `/my-app` for example, that will make Wasp set the `basename` prop of the `Router` to
|
||||
`/my-app`. It will also set the `base` option of the Vite config to `/my-app`.
|
||||
|
||||
This means that if you serve your app from `https://example.com/my-app`, the router will work correctly, and all the assets will be served from `https://example.com/my-app`.
|
||||
|
||||
<BaseDirEnvNote />
|
||||
|
Loading…
Reference in New Issue
Block a user