If you want a run-down of the 1.3 changes and the design decisions behidn those changes, check out the LonestarElixir Phoenix 1.3 keynote: https://www.youtube.com/watch?v=tMO28ar0lW8
To use the new phx.new
project generator, you can install the archive with the following command:
$ mix archive.install https://github.com/phoenixframework/archives/raw/master/phx_new.ez
Phoenix v1.3.0 is a backwards compatible release with v1.2.x. To upgrade your existing 1.2.x project, simply bump your phoenix dependency in mix.exs
:
def deps do
[{:phoenix, "~> 1.3.0-rc"},
...]
end
If using the digest task (mix phoenix.digest), the location of the built manifest has changed from priv/static/manifest.json
to priv/static/cache_manifest.json
. Update your config/prod.exs
endpoint config with the following changes:
-cache_static_manifest: "priv/static/manifest.json"
+cache_static_manifest: "priv/static/cache_manifest.json"
Next, run mix deps.get
and you're all set! Continue reading to jump on the latest project structure conventions (optional).
In mix.exs
, update your elixirc_paths/1
clauses to remove "web":
- defp elixirc_paths(:test), do: ["lib", "web", "test/support"]
- defp elixirc_paths(_), do: ["lib", "web"]
+ defp elixirc_paths(:test), do: ["lib", "test/support"]
+ defp elixirc_paths(_), do: ["lib"]
If you have a reloadable_paths
configuration in your config/dev.exs
, you may remove this value as all elixirc_paths
are now reloaded in dev by default.
The root level web/
directory for new projects has been removed in favor of lib/my_app/web
. Additionally, a Web
namespace convention has been added to isolate the web interface from your elixir application.
Migrate your files to the new structure with the following steps:
$ cd my_app
$ mv web lib/my_app/web
$ mv lib/my_app/endpoint.ex lib/my_app/web/
- Update your view root path in
web.ex
to point to the new template location, and add the:namespace
option:
def view do
quote do
- use Phoenix.View, root: "web/templates"
+ use Phoenix.View, root: "lib/my_app/web/templates",
+ namespace: MyApp.Web
...
- Add the namespace option to your
controller
definition inweb.ex
:
def controller do
quote do
- use Phoenix.Controller
+ use Phoenix.Controller, namespace: MyApp.Web
- Update your aliases in web.ex
controller
,view
, andchannel
definitions to use the newWeb
namespace:
def controller do
quote do
...
- import MyApp.Router.Helpers
+ import MyApp.Web.Router.Helpers
- import MyApp.Gettext
+ import MyApp.Web.Gettext
end
end
def view do
quote do
...
- import MyApp.Router.Helpers
+ import MyApp.Web.Router.Helpers
- import MyApp.ErrorHelpers
+ import MyApp.WebErrorHelpers
- import MyApp.Gettext
+ import MyApp.Web.Gettext
end
end
def channel do
quote do
...
- import MyApp.Gettext
+ import MyApp.Web.Gettext
end
end
- Rename all web related modules in
lib/my_app/web/
(gettext.ex
,controllers/*
,views/*
,channels/*
,endpoint.ex
,router.ex
) to include aWeb
namespace, for example:
MyApp.Endpoint
=>MyApp.Web.Endpoint
MyApp.Router
=>MyApp.Web.Router
MyApp.PageController
=>MyApp.Web.PageController
MyApp.PageView
=>MyApp.Web.PageView
MyApp.UserSocket
=>MyApp.Web.UserSocket
- etc
- Update all alias in
lib/app_name/web/router.ex
to include newWeb
namespace. Most likely you can accomplish this by adding.Web
to the second argument of your scope blocks, for example:
- defmodule MyApp.Router do
+ defmodule MyApp.Web.Router do
...
- scope "/", MyApp do
+ scope "/", MyApp.Web do
pipe_through :browser
resources "/users", UserController
...
end
- Update
endpoint.ex
to use new web modules:
- defmodule MyApp.Endpoint do
+ defmodule MyApp.Web.Endpoint do
...
- socket "/socket", MyApp.UserSocket
+ socket "/socket", MyApp.Web.UserSocket
...
- plug MyApp.Router
+ plug MyApp.Web.Router
- in
lib/my_app.ex
, update your children to reference the new endpoint and remove the config_change callback:
...
children = [
...
- supervisor(MyApp.Endpoint, []),
+ supervisor(MyApp.Web.Endpoint, []),
...
]
...
- def config_change(changed, _new, removed) do
- MyApp.Endpoint.config_change(changed, removed)
- :ok
- end
- Update all endpoint aliases in config/*.exs (config.exs, prod.exs, prod.secret.exs dev.exs, test.exs, etc) aliases to use new
Web
namespace:
- config :my_app, MyApp.Endpoint,
+ config :my_app, MyApp.Web.Endpoint,
...
- render_errors: [view: MyApp.ErrorView, accepts: ~w(html json)],
+ render_errors: [view: MyApp.Web.ErrorView, accepts: ~w(html json)],
...
- Update your live-reload patterns config in
config/dev.exs
:
- config :my_app, MyApp.Endpoint,
+ config :my_app, MyApp.Web.Endpoint,
live_reload: [
patterns: [
~r{priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$},
~r{priv/gettext/.*(po)$},
- ~r{web/views/.*(ex)$},
- ~r{web/templates/.*(eex)$}
+ ~r{lib/my_app/web/views/.*(ex)$},
+ ~r{lib/my_app/web/templates/.*(eex)$}
]
]
- Rename your
test/support/conn_case.ex
andtest/support/channel_case.ex
modules to includeWeb
namespace, and update@endpoint
and router aliases in each:
-defmodule MyApp.ConnCase do
+defmodule MyApp.Web.ConnCase do
using do
quote do
...
- import MyApp.Router.Helpers
+ import MyApp.Web.Router.Helpers
# The default endpoint for testing
- @endpoint MyApp.Endpoint
+ @endpoint MyApp.Web.Endpoint
end
end
...
-defmodule MyApp.ChannelCase do
+defmodule MyApp.Web.ChannelCase do
using do
quote do
...
- @endpoint MyApp.Endpoint
+ @endpoint MyApp.Web.Endpoint
end
end
...
- Update all
test/*/**.exs
references touse MyApp.ConnCase
oruse MyApp.ChannelCase
to use newMyApp.Web.ConnCase
andMyApp.Web.ChannelCase
aliases.
New projects now include a root-level assets/
directory, which serves as a self-contained location for your asset builder's config, source files, and packages. This changer keeps things like node_modules
, package.json
, and brunch-config.js
from leaking into the root of your elixir application. Update your app to the new structure by following these steps:
- move all
web/static/
sources intoassets/
, followed bypackage.json
,node_modules
, andbrunch-config.js
$ mv mv lib/my_app/web/static assets/
$ mv assets/assets assets/static
$ mv package.json assets/
$ mv brunch-config.js assets/
$ rm -rf node_modules
- Update your
asset/package.json
phoenix
andphoenix_html
paths:
"dependencies": {
- "phoenix": "file:deps/phoenix",
+ "phoenix": "file:../deps/phoenix",
- "phoenix_html": "file:deps/phoenix_html"
+ "phoenix_html": "file:../deps/phoenix_html"
},
- Update your
assets/brunch-config.js
to be aware of the new conventions:
conventions: {
- // This option sets where we should place non-css and non-js assets in.
- // By default, we set this to "/web/static/assets". Files in this directory
- // will be copied to `paths.public`, which is "priv/static" by default.
- assets: /^(web\/static\/assets)/
+ // This option sets where we should place non-css and non-js assets in.
+ // By default, we set this to "/assets/static". Files in this directory
+ // will be copied to `paths.public`, which is "priv/static" by default.
+ assets: /^(static)/
},
paths: {
// Dependencies and current project directories to watch
- watched: [
- "web/static",
- "test/static"
- ],
+ watched: ["static", "css", "js", "vendor"],
// Where to compile files to
- public: "priv/static"
+ public: "../priv/static"
},
plugins: {
babel: {
// Do not use ES6 compiler in vendor code
- ignore: [/web\/static\/vendor/]
+ ignore: [/vendor/]
}
},
modules: {
autoRequire: {
- "js/app.js": ["web/static/js/app"]
+ "js/app.js": ["js/app"]
}
},
- Update your
config/dev.exs
watcher to run in the new assets directory:
config :my_app, MyApp.Web.Endpoint,
...
watchers: [node: ["node_modules/brunch/bin/brunch", "watch", "--stdin",
- cd: Path.expand("../", __DIR__)]]
+ cd: Path.expand("../assets", __DIR__)]]
- Install the node deps:
$cd assets && npm install
Test it all with mix phx.server
, and mix test
and you should see:
$ mix phx.server
[info] Running MyApp.Web.Endpoint with Cowboy using http://0.0.0.0:4000
01 Mar 15:40:05 - info: compiled 6 files into 2 files, copied 3 in 976ms