엘릭서 Phoenix migration (1.5 -> 1.6 and scss for esbuild)

1. 우선 scss를 사용하는 상황이었기 때문에 app.scss를 복사해서 app.css로 바꾸고 내용을 삭제. (맨 마지막에 migration을 할 예정임,)

2. `package-lock.json` 파일을 지움.

3. package.json 파일에 내용을 변경 (음.. 일단은 삭제만 했네..)

```
...
    "nprogress": "^0.2.0"
  },
  "devDependencies": {
-    "@babel/core": "^7.0.0",
-    "@babel/preset-env": "^7.0.0",
-    "babel-loader": "^8.0.0",
    "copy-webpack-plugin": "^5.1.1",
    "css-loader": "^3.4.2",
    "sass-loader": "^8.0.2",
    "node-sass": "^4.13.1",
    "hard-source-webpack-plugin": "^0.13.1",
-    "mini-css-extract-plugin": "^0.9.0",
-    "optimize-css-assets-webpack-plugin": "^5.0.1",
-    "terser-webpack-plugin": "^2.3.2",
-    "webpack": "4.41.5",
-    "webpack-cli": "^3.3.2"
    "mini-css-extract-plugin": "^0.9.0"
  }
}
...
```

4. ./assets/webpack.config.js 를 삭제.


5. ./config/config.exs 에 내용을 추가함

```
+ config :esbuild,
+ version: "0.12.18",
+  default: [
+    args: ~w(js/app.js --bundle --target=es2016 --outdir=../priv/static/assets),
+    cd: Path.expand("../assets", __DIR__),
+    env: %{"NODE_PATH" => Path.expand("../deps", __DIR__)}
+  ]
```

6. relay_server/config/dev.exs에 내용 변경
```
  code_reloader: true,
  check_origin: false,
  watchers: [
-    node: [
-      "node_modules/webpack/bin/webpack.js",
-      "--mode",
-      "development",
-      "--watch-stdin",
-      cd: Path.expand("../assets", __DIR__)
-    ]
+    esbuild: {Esbuild, :install_and_run, [:default, ~w(--sourcemap=inline --watch)]}
  ]

```

7. myapp/lib/myapp_web/templates/layout 아래의 app.html.eex, live.html.leex, root.html.leex를 각각 app.html.heex, live.html.heex, root.html.heex 로 변경함.

myapp/lib/myapp_web/templates/layout/root.html.heex에서는 

```
-    
+    
+    
```

8. myapp/lib/myapp_web/endpoint.ex

```
    from: :relay_server,
    gzip: true,
    only:
-      ~w(css firmwares modules fonts images js favicon.ico robots.txt apple-icon-114x114.png apple-icon-180x180.png android-icon-192x192.png manifest.json)
+      ~w(assets css js firmwares modules fonts images favicon.ico robots.txt apple-icon-114x114.png apple-icon-180x180.png android-icon-192x192.png manifest.json)

  # Code reloading can be explicitly enabled under the
  # :code_reloader configuration of your endpoint.
```

9. mix.exs에 변경

```
defmodule Teacher.MixProject do
...
defp deps do
  ...
  {:phoenix, "~> 1.6"},
  {:phoenix_live_view, "~> 0.16.4"},
  {:phoenix_html, "~> 3.0"},
  {:phoenix_live_dashboard, "~> 0.5"},
  {:telemetry_metrics, "~> 0.6"},
  {:telemetry_poller, "~> 0.5"},
  {:esbuild, "~> 0.2", runtime: Mix.env() == :dev},
  ...

end
end



...
defp aliases do
  [
  ...
  "assets.deploy": ["esbuild default --minify", "phx.digest"]
  ]
end
...

```

## source code 변경하기

- TAG 안에 있는 변수를 표현하는 방식이 바뀜 (L 시길 -> H 시길로 변경)
- 최상위 항목을 ` <div>` 태그로  감싸야 함.


```

  def render(assigns) do
-    ~L"""

-    <div class="modal-background<%= if @setting["measure_vod_step_next"] == "step1" do %> on<% end %>">
+    ~H"""
+    <div>
+    <div class={"modal-background #{if @setting["measure_vod_step_next"] == "step1" do " on" end}"}>
        <div class="modal vod-step">
            <div class="modal-header">
			....
	        </div>
        </div>
 + </div>
    """
  end
end

```

라이브 뷰 버튼 혹은 tag 등에서 기존 -> string 기반 에서 속성 에대한 value 지정으로 변경됨.


```


                <button <%= if assigns[:measure_history_filter] == "all" do "disabled" end %>
                phx-click="get_history_data" phx-value-filter="all" phx-value-limit=10
                <button disabled={assigns[:measure_history_filter] == "all"}
                phx-click="get_history_data" phx-value-filter="all" phx-value-limit="10"
                >전체</button>
```


Livecomponent 출 방식이 달라짐

```
                <%= live_component @socket, HeadendComponent, %{id: "#{@idx}_headend", item: @item, result: @result, setting: @setting, idx: @idx} %>
                <%= live_component @socket, MulticastComponent, %{id: "#{@idx}_multicast", item: @item, result: @result, setting: @setting, idx: @idx, machine_status: @machine_status} %>
                <%= live_component HeadendComponent, %{id: "#{@idx}_headend", item: @item, result: @result, setting: @setting, idx: @idx} %>
                <%= live_component MulticastComponent, %{id: "#{@idx}_multicast", item: @item, result: @result, setting: @setting, idx: @idx, machine_status: @machine_status} %>
                <div class="content unit-content">
                    <h3>CRC 에러</h3>
                    <div class="box">
@@ -39,29 +55,29 @@ defmodule MeasureNtossIptvComponent do
                    </div>
                </div>
            </div>
            <%= live_component @socket, RadioMeasurePositionComponent, %{idx: @idx, result: @result, item: @item} %>
            <%= live_component RadioMeasurePositionComponent, %{idx: @idx, result: @result, item: @item} %>
```

 form이 변경됨
 
```


-                <%= f = form_for :vod_information, "#", [phx_submit: :measure_vod_set_step] %>
+                <.form let={f} for={:vod_information} phx-submit={:measure_vod_set_step}>

                  <%= text_input f, "contents_name", placeholder: "컨텐츠 명/시즌"%>
                  <%= number_input f, "contents_number", placeholder: "회차"%>
                  <%= hidden_input(f, "idx", value:  @idx ) %>
                  <%= submit "다음", class: "btn-submit btn-block" %>

-                </form>
+                </.form>
```

## Stateless livecomponent들은 다음과 같이. Phoenix.LiveComponent => Phoenix.Component로 쓸 것

```
defmodule HistoryComponentSpeed do
  # use Phoenix.LiveComponent
  use Phoenix.Component

  def render(assigns) do
    ~H"""
      %<div class="result-wrapper speed"%>
        %<div class="date"%>

```

호출 방식도 key value list에서 map으로 변경 된 듯 하다!!

```
                                    # HistoryComponentSpeed.render(test: data, id: "#{assigns[:measure_history_filter]}speed_#{measure_uuid}", converted_time: converted_time, purpose: purpose, machine_type_map: @measure_history_machine_map)
                                    HistoryComponentSpeed.render(%{test: data, converted_time: converted_time, purpose: purpose, machine_type_map: @measure_history_machine_map})

```
  
## 


## SCSS 관련 적용문제

[Elixir Phoenix 1.6 Esbuild + SCSS](https://dev.to/mnishiguchi/elixir-phoenix-16-esbuild-scss-1go7) => 이 사이트를 참조 하여 작업


https://mfeckie.dev/sass-in-phoenix/ = 이곳에도 어느정도 정리가 되어 있음.

https://github.com/CargoSense/dart_sass


[1] [#138: Upgrading to Phoenix 1.6](https://elixircasts.io/upgrading-to-phoenix-1.6) > 이 instruction을 보고 작업 하였음.
[1] [Phoenix 1.5.x to 1.6 upgrade instructions](https://gist.github.com/chrismccord/2ab350f154235ad4a4d0f4de6decba7b) => 이것을 봤어야 한다고 생각함.
[1] [Elixir Phoenix 1.6 Esbuild + SCSS](https://dev.to/mnishiguchi/elixir-phoenix-16-esbuild-scss-1go7)

댓글

이 블로그의 인기 게시물

윈도우 디스크 관리세어 삭제 불가능 파티션 삭제 (필요해서 찾아봄)