Repository: gohugoio/hugo (language: go)

Issue:
Make the server flag --renderToDisk into --renderToMemory
I'm doing some testing on some beefy (big) sites with the new Hugo code (one of the new features is better memory management), and I have come to the conclusion that it's stupid to have the server render to memory as a default. 

* It only makes sense on small setups.
* And even then, with fast modern disks and fast render mode, the savings is very small.
* There's also some known issues with PostCSS etc. that doesn't work well with things in memory.

I think the timing for doing this is also good, so If I don't see many convincing protests about this, I'm doing it.

/cc @jmooring 



Discussion / hints:
This sounds like a good idea. A few thoughts/questions...

1. What if someone has configured their `publishDir` or `--destination` flag to something slow (e.g., network location)?  If that happens, will they still be able to use the `--renderToMemory` flag? It seems like we would want to keep both of the `--renderToSomething` flags, but change the default behavior.

3. We do not clear the `publishDir` when building with either `hugo` or `hugo server`. So previously published content that has since been deleted will still exist in the `publishDir`. I wouldn't think that would be a problem, but it is conceptually different from rendering to memory.
1. I'm not sure I understand. For the server we have (ok, this isn't entirely true) only one flag in this area: `--renderToDisk`. We could make `--renderToDisk=true` the new default, but making it `--renderToMemory` will make it behave exactly like the regular `hugo` command. Not sure what having both `--renderToMemory`  and `--renderToDisk` would give, other than confusion. 
2. Yea, that's true, but one could argue that this will create less surprises, making the server build closer to the production build.



For some reason I thought we already had two flags, so disregard that bit. As long as someone can run:

```text
hugo server --renderToDisk=false
```
>hugo server --renderToDisk=false

Just to be clear, for the server command, we:

* Remove the ` --renderToDisk` flag
* Add the `--renderToMemory` flag (a flag we already have on the `hugo` command)
* The default behaviour is to always render to disk (both for the server and regular builds).

LGTM.

Fix patch:
diff --git a/commands/commandeer.go b/commands/commandeer.go
index 0052d91b4c6..82d684153a5 100644
--- a/commands/commandeer.go
+++ b/commands/commandeer.go
@@ -203,9 +203,6 @@ func (r *rootCommand) ConfigFromProvider(key int32, cfg config.Provider) (*commo
 			cfg = config.New()
 		}
 
-		if !cfg.IsSet("renderToDisk") {
-			cfg.Set("renderToDisk", true)
-		}
 		if !cfg.IsSet("workingDir") {
 			cfg.Set("workingDir", dir)
 		} else {
@@ -239,9 +236,7 @@ func (r *rootCommand) ConfigFromProvider(key int32, cfg config.Provider) (*commo
 
 		sourceFs := hugofs.Os
 		var destinationFs afero.Fs
-		if cfg.GetBool("renderToDisk") {
-			destinationFs = hugofs.Os
-		} else {
+		if cfg.GetBool("renderToMemory") {
 			destinationFs = afero.NewMemMapFs()
 			if renderStaticToDisk {
 				// Hybrid, render dynamic content to Root.
@@ -251,6 +246,8 @@ func (r *rootCommand) ConfigFromProvider(key int32, cfg config.Provider) (*commo
 				cfg.Set("publishDirDynamic", "/")
 				cfg.Set("publishDirStatic", "/")
 			}
+		} else {
+			destinationFs = hugofs.Os
 		}
 
 		fs := hugofs.NewFromSourceAndDestination(sourceFs, destinationFs, cfg)
@@ -498,6 +495,7 @@ Complete documentation is available at https://gohugo.io/.`
 	cmd.PersistentFlags().StringVar(&r.cfgFile, "config", "", "config file (default is hugo.yaml|json|toml)")
 	cmd.PersistentFlags().StringVar(&r.cfgDir, "configDir", "config", "config dir")
 	cmd.PersistentFlags().BoolVar(&r.quiet, "quiet", false, "build in quiet mode")
+	cmd.PersistentFlags().BoolVar(&r.renderToMemory, "renderToMemory", false, "render to memory (mostly useful when running the server)")
 
 	// Set bash-completion
 	_ = cmd.PersistentFlags().SetAnnotation("config", cobra.BashCompFilenameExt, config.ValidConfigFileExtensions)
@@ -506,7 +504,6 @@ Complete documentation is available at https://gohugo.io/.`
 	cmd.PersistentFlags().BoolVarP(&r.debug, "debug", "", false, "debug output")
 	cmd.PersistentFlags().StringVar(&r.logLevel, "logLevel", "", "log level (debug|info|warn|error)")
 	cmd.Flags().BoolVarP(&r.buildWatch, "watch", "w", false, "watch filesystem for changes and recreate as needed")
-	cmd.Flags().BoolVar(&r.renderToMemory, "renderToMemory", false, "render to memory (only useful for benchmark testing)")
 
 	// Configure local flags
 	applyLocalFlagsBuild(cmd, r)
diff --git a/commands/hugobuilder.go b/commands/hugobuilder.go
index 190c12f599b..6ae9640b08c 100644
--- a/commands/hugobuilder.go
+++ b/commands/hugobuilder.go
@@ -928,7 +928,7 @@ func (c *hugoBuilder) hugoTry() *hugolib.HugoSites {
 
 func (c *hugoBuilder) loadConfig(cd *simplecobra.Commandeer, running bool) error {
 	cfg := config.New()
-	cfg.Set("renderToDisk", (c.s == nil && !c.r.renderToMemory) || (c.s != nil && c.s.renderToDisk))
+	cfg.Set("renderToMemory", c.r.renderToMemory)
 	watch := c.r.buildWatch || (c.s != nil && c.s.serverWatch)
 	if c.r.environment == "" {
 		// We need to set the environment as early as possible because we need it to load the correct config.
diff --git a/commands/server.go b/commands/server.go
index 574f5c3404c..e803d48249e 100644
--- a/commands/server.go
+++ b/commands/server.go
@@ -239,12 +239,14 @@ func (f *fileServer) createEndpoint(i int) (*http.ServeMux, net.Listener, string
 	r.Printf("Environment: %q\n", f.c.hugoTry().Deps.Site.Hugo().Environment)
 
 	if i == 0 {
-		if f.c.renderToDisk {
-			r.Println("Serving pages from disk")
-		} else if f.c.renderStaticToDisk {
-			r.Println("Serving pages from memory and static files from disk")
+		mainTarget := "disk"
+		if f.c.r.renderToMemory {
+			mainTarget = "memory"
+		}
+		if f.c.renderStaticToDisk {
+			r.Printf("Serving pages from %s and static files from disk\n", mainTarget)
 		} else {
-			r.Println("Serving pages from memory")
+			r.Printf("Serving pages from %s\n", mainTarget)
 		}
 	}
 
@@ -444,7 +446,6 @@ type serverCommand struct {
 	doLiveReload bool
 
 	// Flags.
-	renderToDisk        bool
 	renderStaticToDisk  bool
 	navigateToChanged   bool
 	serverAppend        bool
@@ -516,8 +517,9 @@ func (c *serverCommand) Init(cd *simplecobra.Commandeer) error {
 	cmd.Long = `Hugo provides its own webserver which builds and serves the site.
 While hugo server is high performance, it is a webserver with limited options.
 
-'hugo server' will avoid writing the rendered and served content to disk,
-preferring to store it in memory.
+'hugo server' will by default write and server files from disk, but you can
+render to memory by using the '--renderToMemory' flag. This can be faster
+in some cases, but it will consume more memory.
 
 By default hugo will also watch your files for any changes you make and
 automatically rebuild the site. It will then live reload any open browser pages
@@ -537,7 +539,6 @@ of a second, you will be able to save and see your changes nearly instantly.`
 	cmd.Flags().BoolVarP(&c.serverAppend, "appendPort", "", true, "append port to baseURL")
 	cmd.Flags().BoolVar(&c.disableLiveReload, "disableLiveReload", false, "watch without enabling live browser reload on rebuild")
 	cmd.Flags().BoolVar(&c.navigateToChanged, "navigateToChanged", false, "navigate to changed content file on live browser reload")
-	cmd.Flags().BoolVar(&c.renderToDisk, "renderToDisk", false, "serve all files from disk (default is from memory)")
 	cmd.Flags().BoolVar(&c.renderStaticToDisk, "renderStaticToDisk", false, "serve static files from disk and dynamic files from memory")
 	cmd.Flags().BoolVar(&c.disableFastRender, "disableFastRender", false, "enables full re-renders on changes")
 	cmd.Flags().BoolVar(&c.disableBrowserError, "disableBrowserError", false, "do not show build errors in the browser")
@@ -589,7 +590,9 @@ func (c *serverCommand) PreRun(cd, runner *simplecobra.Commandeer) error {
 	)
 
 	destinationFlag := cd.CobraCommand.Flags().Lookup("destination")
-	c.renderToDisk = c.renderToDisk || (destinationFlag != nil && destinationFlag.Changed)
+	if c.r.renderToMemory && (destinationFlag != nil && destinationFlag.Changed) {
+		return fmt.Errorf("cannot use --renderToMemory with --destination")
+	}
 	c.doLiveReload = !c.disableLiveReload
 	c.fastRenderMode = !c.disableFastRender
 	c.showErrorInBrowser = c.doLiveReload && !c.disableBrowserError


Test patch:
diff --git a/testscripts/commands/server.txt b/testscripts/commands/server.txt
index 777a9145480..83e3ceafdb6 100644
--- a/testscripts/commands/server.txt
+++ b/testscripts/commands/server.txt
@@ -1,7 +1,7 @@
 # Test the hugo server command.
 
 # We run these tests in parallel so let Hugo decide which port to use.
-hugo server --gc &
+hugo server --renderToMemory --gc &
 
 waitServer
 
diff --git a/testscripts/commands/server__edit_config.txt b/testscripts/commands/server__edit_config.txt
index e3972bf071e..3997ca895a9 100644
--- a/testscripts/commands/server__edit_config.txt
+++ b/testscripts/commands/server__edit_config.txt
@@ -1,7 +1,7 @@
 # Test the hugo server command when editing the config file.
 
 # We run these tests in parallel so let Hugo decide which port to use.
-hugo server &
+hugo server --renderToMemory &
 
 waitServer
 
diff --git a/testscripts/commands/server__edit_content.txt b/testscripts/commands/server__edit_content.txt
index 5a2d9d502fc..0aca2e892fa 100644
--- a/testscripts/commands/server__edit_content.txt
+++ b/testscripts/commands/server__edit_content.txt
@@ -2,7 +2,7 @@
 
 # We run these tests in parallel so let Hugo decide which port to use.
 # Render to disk so we can check the /public dir.
-hugo server --renderToDisk &
+hugo server &
 
 waitServer
 
diff --git a/testscripts/commands/server__multihost.txt b/testscripts/commands/server__multihost.txt
index 492cac855a5..8888863701d 100644
--- a/testscripts/commands/server__multihost.txt
+++ b/testscripts/commands/server__multihost.txt
@@ -1,7 +1,7 @@
 # Test the hugo server command.
 
 # We run these tests in parallel so let Hugo decide which port to use.
-hugo server &
+hugo server --renderToMemory &
 
 waitServer
 
diff --git a/testscripts/commands/server__watch_hugo_stats.txt b/testscripts/commands/server__watch_hugo_stats.txt
index 179e59f8d8b..da4ffc19f40 100644
--- a/testscripts/commands/server__watch_hugo_stats.txt
+++ b/testscripts/commands/server__watch_hugo_stats.txt
@@ -1,4 +1,4 @@
-hugo server  &
+hugo server  --renderToMemory &
 
 waitServer
 stopServer
diff --git a/testscripts/commands/server__watch_moduleconfig.txt b/testscripts/commands/server__watch_moduleconfig.txt
index 867669754f4..bd84a1449f0 100644
--- a/testscripts/commands/server__watch_moduleconfig.txt
+++ b/testscripts/commands/server__watch_moduleconfig.txt
@@ -1,4 +1,4 @@
-hugo server --disableLiveReload  &
+hugo server --renderToMemory --disableLiveReload  &
 
 waitServer
 stopServer
diff --git a/testscripts/commands/server_disablelivereload.txt b/testscripts/commands/server_disablelivereload.txt
index 6b1cd66cbee..f3f163c830b 100644
--- a/testscripts/commands/server_disablelivereload.txt
+++ b/testscripts/commands/server_disablelivereload.txt
@@ -1,4 +1,4 @@
-hugo server --renderToDisk --disableLiveReload &
+hugo server --disableLiveReload &
 
 waitServer
 
diff --git a/testscripts/commands/server_disablelivereload__config.txt b/testscripts/commands/server_disablelivereload__config.txt
index fe49ff2471d..a71cde12b59 100644
--- a/testscripts/commands/server_disablelivereload__config.txt
+++ b/testscripts/commands/server_disablelivereload__config.txt
@@ -1,4 +1,4 @@
-hugo server --renderToDisk &
+hugo server &
 
 waitServer
 
diff --git a/testscripts/commands/server_render_static_to_disk.txt b/testscripts/commands/server_render_static_to_disk.txt
index b0e76e318ce..98d6c0de881 100644
--- a/testscripts/commands/server_render_static_to_disk.txt
+++ b/testscripts/commands/server_render_static_to_disk.txt
@@ -1,7 +1,7 @@
 # Test the hugo server command.
 
 # We run these tests in parallel so let Hugo decide which port to use.
-hugo server --renderStaticToDisk &
+hugo server --renderToMemory --renderStaticToDisk &
 
 waitServer
 
diff --git a/testscripts/commands/server_render_to_memory.txt b/testscripts/commands/server_render_to_memory.txt
index 368efe41d11..afff92126b3 100644
--- a/testscripts/commands/server_render_to_memory.txt
+++ b/testscripts/commands/server_render_to_memory.txt
@@ -2,7 +2,7 @@
 
 # We run these tests in parallel so let Hugo decide which port to use.
 # Deliberately using the alias 'serve' here.
-hugo serve &
+hugo serve --renderToMemory &
 
 waitServer