@@ -40,41 +40,77 @@ pub struct BuildTargets {
4040 pub server : Option < BuildRequest > ,
4141}
4242
43- impl BuildArgs {
44- fn default_client ( & self ) -> & TargetArgs {
45- & self . build_arguments
46- }
43+ impl CommandWithPlatformOverrides < BuildArgs > {
44+ /// We need to decompose the combined `BuildArgs` into the individual targets that we need to build.
45+ ///
46+ /// Only in a few cases do we spin out an additional server binary:
47+ /// - the fullstack feature is passed
48+ /// - the fullstack flag is enabled
49+ /// - the server flag is enabled
50+ ///
51+ /// The buildtargets configuration comes in two flavors:
52+ /// - implied via the `fullstack` feature
53+ /// - explicit when using `@server and @client`
54+ ///
55+ /// We use the client arguments to build the client target, and then make a few changes to make
56+ /// the server target.
57+ ///
58+ /// The `--fullstack` feature is basically the same as passing `--features fullstack`
59+ ///
60+ /// Some examples:
61+ /// ```shell, ignore
62+ /// dx serve --target wasm32-unknown-unknown --fullstack # serves both client and server
63+ /// dx serve --target wasm32-unknown-unknown --features fullstack # serves both client and server
64+ /// dx serve --target wasm32-unknown-unknown # only serves the client
65+ /// dx serve --target wasm32-unknown-unknown # servers both if `fullstack` is enabled on dioxus
66+ /// dx serve @client --target wasm32-unknown-unknown # only serves the client
67+ /// dx serve @client --target wasm32-unknown-unknown --fullstack # serves both client and server
68+ /// ```
69+ ///
70+ /// Currently it is not possible to serve the server without the client, but this could be added in the future.
71+ pub async fn into_targets ( self ) -> Result < BuildTargets > {
72+ let workspace = Workspace :: current ( ) . await ?;
73+
74+ // do some logging to ensure dx matches the dioxus version since we're not always API compatible
75+ workspace. check_dioxus_version_against_cli ( ) ;
76+
77+ // The client args are the `@client` arguments, or the shared build arguments if @client is not specified.
78+ let client_args = & self . client . as_ref ( ) . unwrap_or ( & self . shared ) . build_arguments ;
79+
80+ // Create the client build request
81+ let client = BuildRequest :: new ( client_args, None , workspace. clone ( ) ) . await ?;
82+
83+ // Create the server build request if needed
84+ // This happens when 1) fullstack is enabled, 2)
85+ let mut server = None ;
86+ if matches ! ( self . shared. fullstack, Some ( true ) )
87+ || client. fullstack_feature_enabled ( )
88+ || self . server . is_some ( )
89+ {
90+ match self . server . as_ref ( ) {
91+ Some ( server_args) => {
92+ server = Some (
93+ BuildRequest :: new (
94+ & server_args. build_arguments ,
95+ Some ( client. main_target . clone ( ) ) ,
96+ workspace. clone ( ) ,
97+ )
98+ . await ?,
99+ ) ;
100+ }
101+ None => {
102+ let mut args = self . shared . build_arguments . clone ( ) ;
103+ args. platform = Some ( crate :: Platform :: Server ) ;
104+ args. renderer . renderer = Some ( crate :: Renderer :: Server ) ;
105+ args. target = Some ( target_lexicon:: Triple :: host ( ) ) ;
106+ server = Some ( BuildRequest :: new ( & args, None , workspace. clone ( ) ) . await ?) ;
107+ }
108+ }
109+ }
47110
48- fn default_server ( & self , client : & BuildRequest ) -> Option < & TargetArgs > {
49- // Now resolve the builds that we need to.
50- // These come from the args, but we'd like them to come from the `TargetCmd` chained object
51- //
52- // The process here is as follows:
53- //
54- // - Create the BuildRequest for the primary target
55- // - If that BuildRequest is "fullstack", then add the client features
56- // - If that BuildRequest is "fullstack", then also create a BuildRequest for the server
57- // with the server features
58- //
59- // This involves modifying the BuildRequest to add the client features and server features
60- // only if we can properly detect that it's a fullstack build. Careful with this, since
61- // we didn't build BuildRequest to be generally mutable.
62- let default_server = client. enabled_renderers . contains ( & crate :: Renderer :: Server ) ;
63-
64- // Make sure we set the fullstack platform so we actually build the fullstack variant
65- // Users need to enable "fullstack" in their default feature set.
66- // todo(jon): fullstack *could* be a feature of the app, but right now we're assuming it's always enabled
67- //
68- // Now we need to resolve the client features
69- let fullstack = ( ( default_server || client. fullstack_feature_enabled ( ) )
70- || self . fullstack . unwrap_or ( false ) )
71- && self . fullstack != Some ( false ) ;
72-
73- fullstack. then_some ( & self . build_arguments )
111+ Ok ( BuildTargets { client, server } )
74112 }
75- }
76113
77- impl CommandWithPlatformOverrides < BuildArgs > {
78114 pub async fn build ( self ) -> Result < StructuredOutput > {
79115 tracing:: info!( "Building project..." ) ;
80116
@@ -105,37 +141,4 @@ impl CommandWithPlatformOverrides<BuildArgs> {
105141 server : targets. server . map ( |s| s. root_dir ( ) ) ,
106142 } )
107143 }
108-
109- pub async fn into_targets ( self ) -> Result < BuildTargets > {
110- let workspace = Workspace :: current ( ) . await ?;
111-
112- // do some logging to ensure dx matches the dioxus version since we're not always API compatible
113- workspace. check_dioxus_version_against_cli ( ) ;
114-
115- let client_args = match & self . client {
116- Some ( client) => & client. build_arguments ,
117- None => self . shared . default_client ( ) ,
118- } ;
119- let client = BuildRequest :: new ( client_args, None , workspace. clone ( ) ) . await ?;
120-
121- let server_args = match & self . server {
122- Some ( server) => Some ( & server. build_arguments ) ,
123- None => self . shared . default_server ( & client) ,
124- } ;
125-
126- let mut server = None ;
127- // If there is a server, make sure we output in the same directory as the client build so we use the server
128- // to serve the web client
129- if let Some ( server_args) = server_args {
130- // Copy the main target from the client to the server
131- let main_target = client. main_target . clone ( ) ;
132- let mut server_args = server_args. clone ( ) ;
133- // The renderer in the server build is always set to Server
134- server_args. renderer . renderer = Some ( crate :: Renderer :: Server ) ;
135- server =
136- Some ( BuildRequest :: new ( & server_args, Some ( main_target) , workspace. clone ( ) ) . await ?) ;
137- }
138-
139- Ok ( BuildTargets { client, server } )
140- }
141144}
0 commit comments