Repository: phoenixframework/phoenix
Pull request #3334 (2019-03-28 10:04:11)

Incorporate some of LiveView steps into Phoenix
Although this means Phoenix knows a bit about LiveView,
it is justified as LiveView is shaping to became an important
asset in the Elixir community and it will help with its getting
started experience.


Patch:
diff --git a/guides/deployment/heroku.md b/guides/deployment/heroku.md
index 5ef88cfac..35f1a2b99 100644
--- a/guides/deployment/heroku.md
+++ b/guides/deployment/heroku.md
@@ -75,17 +75,17 @@ Now that we have the Toolbelt installed, let's create the Heroku application. In
 
 > Note: the first time we use a Heroku command, it may prompt us to log in. If this happens, just enter the email and password you specified during signup.
 
+We are going to use latest published buildpack, you can also get an edge version of this buildpack. See it's [README](https://github.com/HashNuke/heroku-buildpack-elixir) for more instructions on how to do this.
 ```console
-$ heroku create --buildpack "https://github.com/HashNuke/heroku-buildpack-elixir.git"
-Creating mysterious-meadow-6277... done, stack is cedar-14
-Buildpack set. Next release on mysterious-meadow-6277 will use https://github.com/HashNuke/heroku-buildpack-elixir.git.
+$ heroku create --buildpack hashnuke/elixir
+Creating app... done, ⬢ mysterious-meadow-6277
+Setting buildpack to hashnuke/elixir... done
 https://mysterious-meadow-6277.herokuapp.com/ | https://git.heroku.com/mysterious-meadow-6277.git
-Git remote heroku added
 ```
 
 > Note: the name of the Heroku application is the random string after "Creating" in the output above (mysterious-meadow-6277). This will be unique, so expect to see a different name from "mysterious-meadow-6277".
 
-The `--buildpack` option we are passing allows us to specify the [Elixir buildpack](https://github.com/HashNuke/heroku-buildpack-elixir) we want Heroku to use. A [buildpack](https://devcenter.heroku.com/articles/buildpacks) is a convenient way of packaging framework and/or runtime support. In our case it's installing Erlang, Elixir, fetching our application dependencies, and so on, before we run it.
+A [buildpack](https://devcenter.heroku.com/articles/buildpacks) is a convenient way of packaging framework and/or runtime support. In our case it's installing Erlang, Elixir, fetching our application dependencies, and so on, before we run it.
 
 The URL in the output is the URL to our application. If we open it in our browser now, we will get the default Heroku welcome page.
 
@@ -108,31 +108,15 @@ We need to compile static assets for a successful Phoenix deployment. The [Phoen
 
 _Skip this step if you do not have any static assets (i.e. you created your project with the `--no-webpack --no-html` flags)._
 
+
 ```console
 $ heroku buildpacks:add https://github.com/gjaldon/heroku-buildpack-phoenix-static.git
 Buildpack added. Next release on mysterious-meadow-6277 will use:
   1. https://github.com/HashNuke/heroku-buildpack-elixir.git
   2. https://github.com/gjaldon/heroku-buildpack-phoenix-static.git
-Run `git push heroku master` to create a new release using these buildpacks.
-```
-
-This phoenix static buildpack pack can be configured to change the node version and compile options. Please refer to the [configuration section](https://github.com/gjaldon/heroku-buildpack-phoenix-static#configuration) for full details. We will override the compile options here.
-
-Create a config file named `phoenix_static_buildpack.config` in the root directory for your project with the following:
-
-```
-compile="compile"
 ```
 
-And a file named `compile` with the following contents:
-
-```
-npm run deploy
-cd $phoenix_dir
-mix "${phoenix_ex}.digest"
-```
-
-This will ensure that the `deploy` script in the package.json is used instead of the static buildpack default of `brunch`.
+This phoenix static buildpack pack can be configured to change the node version and compile options. Please refer to the [configuration section](https://github.com/gjaldon/heroku-buildpack-phoenix-static#configuration) for full details. You can make your own custom build script, but for now we will use the [default one provided](https://github.com/gjaldon/heroku-buildpack-phoenix-static/blob/master/compile).
 
 ## Making our Project ready for Heroku
 
@@ -149,23 +133,13 @@ config :hello, HelloWeb.Endpoint,
   secret_key_base: System.get_env("SECRET_KEY_BASE") || raise("missing SECRET_KEY_BASE env var")
 ```
 
-Then, we'll add the production database configuration to `config/prod.exs`:
-
-```elixir
-# Configure your database
-config :hello, Hello.Repo,
-  url: System.get_env("DATABASE_URL"),
-  pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10"),
-  ssl: true
-```
-
-Afterwards, let's tell the Phoenix application to bind to the PORT environment variable provided by Heroku's [dyno networking](https://devcenter.heroku.com/articles/dynos#common-runtime-networking) so that it can accept incoming web traffic. Add this beneath your endpoint configuration:
+Next let's tell the Phoenix application to bind to the PORT environment variable provided by Heroku's [dyno networking](https://devcenter.heroku.com/articles/dynos#common-runtime-networking) so that it can accept incoming web traffic. Add this anywhere within your endpoint configuration:
 
 ```elixir
 http: [port: System.get_env("PORT")]
 ```
 
-Now, let's tell Phoenix to use our Heroku URL and enforce we only use the SSL version of the website. Find the url line:
+Now, let's tell Phoenix to use our Heroku URL and enforce we only use the SSL version of the website. If we don't override the `host` variable, then when using plugs like `Routes.page_url` (`Routes.page_path` is unaffected as it uses relative URL's) the URL will generate incorrectly. Find the url line:
 
 ```elixir
 url: [host: "example.com", port: 80],
@@ -174,14 +148,18 @@ url: [host: "example.com", port: 80],
 ... and replace it with this (don't forget to replace `mysterious-meadow-6277` with your application name):
 
 ```elixir
-url: [scheme: "https", host: "mysterious-meadow-6277.herokuapp.com", port: 443],
+url: [scheme: "https", host: "mysterious-meadow-6277", port: 443],
 force_ssl: [rewrite_on: [:x_forwarded_proto]],
 ```
 
-... finally, if you would like to use a custom domain that has already been added to the Heroku app settings, replace the host with your custom domain and update the port to use Heroku's `PORT` environment variable:
+Then, we'll add the production database configuration to `config/prod.exs`:
 
 ```elixir
-url: [scheme: "https", host: "mywebsite.com", port: System.get_env("PORT")],
+# Configure your database
+config :hello, Hello.Repo,
+  url: System.get_env("DATABASE_URL"),
+  pool_size: String.to_integer(System.get_env("POOL_SIZE") || "10"),
+  ssl: true
 ```
 
 Since our configuration is now handled using Heroku's environment variables, we don't need to import the `config/prod.secret.exs` file in `/config/prod.exs` any longer, so we can delete the following line:
@@ -214,7 +192,7 @@ config :hello, Hello.Repo,
   ssl: true
 ```
 
-Finally, we need to decrease the timeout for the websocket transport in `lib/hello_web/endpoint.ex`:
+Finally, if you plan on using websockets, then we will need to decrease the timeout for the websocket transport in `lib/hello_web/endpoint.ex`. If you do not plan on using websockets, then leaving it set to false is fine. You can find further explanation of the options available at the [documentation](https://hexdocs.pm/phoenix/Phoenix.Endpoint.html#socket/3-websocket-configuration).
 
 ```elixir
 defmodule HelloWeb.Endpoint do
@@ -230,11 +208,7 @@ end
 
 This ensures that any idle connections are closed by Phoenix before they reach Heroku's 55-second timeout window.
 
-Lastly, we'll need to create a [Procfile](https://devcenter.heroku.com/articles/procfile) (a text file called "Procfile" in the root of our project’s folder) with the following line:
-
-```
-web: MIX_ENV=prod elixir --sname server -S mix phx.server
-```
+As is common with Heroku's buildpacks, you can create your own "Procfile", but for our case we will use the default one provided by the [heroku-buildpack-phoenix-static buildpack](https://github.com/gjaldon/heroku-buildpack-phoenix-static). Since we are using multiple buildpacks, you might run into an issue where the sequence is out of order (the Elixir buildpack needs to run before the Phoenix Static buildpack). [Heroku's docs](https://devcenter.heroku.com/articles/using-multiple-buildpacks-for-an-app) explain this better, but you will need to check on the sequence these are defined for your app.
 
 ## Creating Environment Variables in Heroku
 
diff --git a/installer/templates/phx_single/config/dev.exs b/installer/templates/phx_single/config/dev.exs
index 5c3c6b427..8e9cbbb3d 100644
--- a/installer/templates/phx_single/config/dev.exs
+++ b/installer/templates/phx_single/config/dev.exs
@@ -49,10 +49,10 @@ config :<%= app_name %>, <%= endpoint_module %>,
 config :<%= app_name %>, <%= endpoint_module %>,
   live_reload: [
     patterns: [
-      ~r{priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$},
-      ~r{priv/gettext/.*(po)$},
-      ~r{lib/<%= lib_web_name %>/views/.*(ex)$},
-      ~r{lib/<%= lib_web_name %>/templates/.*(eex)$}
+      ~r"priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$",
+      ~r"priv/gettext/.*(po)$",
+      ~r"lib/<%= lib_web_name %>/{live,views}/.*(ex)$",
+      ~r"lib/<%= lib_web_name %>/templates/.*(eex)$"
     ]
   ]<% end %>
 
diff --git a/installer/templates/phx_umbrella/apps/app_name_web/config/dev.exs b/installer/templates/phx_umbrella/apps/app_name_web/config/dev.exs
index 3916c9680..f00851b5b 100644
--- a/installer/templates/phx_umbrella/apps/app_name_web/config/dev.exs
+++ b/installer/templates/phx_umbrella/apps/app_name_web/config/dev.exs
@@ -53,9 +53,9 @@ config :<%= web_app_name %>, <%= endpoint_module %>,
 config :<%= web_app_name %>, <%= endpoint_module %>,
   live_reload: [
     patterns: [
-      ~r{priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$},
-      ~r{priv/gettext/.*(po)$},
-      ~r{lib/<%= web_app_name %>/views/.*(ex)$},
-      ~r{lib/<%= web_app_name %>/templates/.*(eex)$}
+      ~r"priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$",
+      ~r"priv/gettext/.*(po)$",
+      ~r"lib/<%= web_app_name %>/{live,views}/.*(ex)$",
+      ~r"lib/<%= web_app_name %>/templates/.*(eex)$"
     ]
   ]<% end %>
diff --git a/lib/phoenix/template.ex b/lib/phoenix/template.ex
index b18ac001d..ea1d6c1fd 100644
--- a/lib/phoenix/template.ex
+++ b/lib/phoenix/template.ex
@@ -99,7 +99,12 @@ defmodule Phoenix.Template do
 
   alias Phoenix.Template
 
-  @engines  [eex: Phoenix.Template.EExEngine, exs: Phoenix.Template.ExsEngine]
+  @engines [
+    eex: Phoenix.Template.EExEngine,
+    exs: Phoenix.Template.ExsEngine,
+    leex: Phoenix.LiveView.Engine
+  ]
+
   @default_pattern "*"
 
   defmodule UndefinedError do


Test patch:
diff --git a/installer/test/phx_new_test.exs b/installer/test/phx_new_test.exs
index 680f41c1d..e09b16358 100644
--- a/installer/test/phx_new_test.exs
+++ b/installer/test/phx_new_test.exs
@@ -93,7 +93,7 @@ defmodule Mix.Tasks.Phx.NewTest do
       assert_file "phx_blog/assets/.babelrc", "env"
       assert_file "phx_blog/config/dev.exs", fn file ->
         assert file =~ "watchers: [\n    node:"
-        assert file =~ "lib/phx_blog_web/views/.*(ex)"
+        assert file =~ "lib/phx_blog_web/{live,views}/.*(ex)"
         assert file =~ "lib/phx_blog_web/templates/.*(eex)"
       end
       assert_file "phx_blog/assets/static/favicon.ico"
diff --git a/installer/test/phx_new_umbrella_test.exs b/installer/test/phx_new_umbrella_test.exs
index a77eea082..1d6a59b1c 100644
--- a/installer/test/phx_new_umbrella_test.exs
+++ b/installer/test/phx_new_umbrella_test.exs
@@ -132,7 +132,7 @@ defmodule Mix.Tasks.Phx.New.UmbrellaTest do
       assert_file web_path(@app, "assets/.babelrc"), "env"
       assert_file web_path(@app, "config/dev.exs"), fn file ->
         assert file =~ ~r/watchers: \[\s+node:/
-        assert file =~ "lib/#{@app}_web/views/.*(ex)"
+        assert file =~ "lib/#{@app}_web/{live,views}/.*(ex)"
         assert file =~ "lib/#{@app}_web/templates/.*(eex)"
       end
       assert_file web_path(@app, "assets/static/favicon.ico")