We've been using Elm in production for https://halogen.tv and has been a great experience overall.
The codebase is around 60k LOC for the front-end and we've settled on a few patterns that help with reusability and managing complexity.
- We have moved to a very flat architecture where most things are at the top level of the state tree
- We use web components to wrap up things that are a pain in Elm (like exit animations, fancy text editors, interop with various JS libraries)
- Our reusable components take Configs so that the components are not tied to one Msg type, different pages have to provide hookups for those messages but it allows us to reuse components on different pages pretty easily.
Refactoring with confidence is possible! I have worked on large React/Angular apps where it was nigh impossible to refactor something without breaking a bunch of others things (often without a way to know they are broken aside from a full regression test). Typescript has improved things quite a bit, but it can't give you the same guarantees as Elm can.
As for difficulties we've run into:
- The virtual dom diffing slows down as the number of nodes grows, for our live chat we can have thousands of people chatting at once and diffing between the previous/next set of nodes can easily exceed the time we have for the next frame. We've taken to reducing the scrollback available in chat, virtualizing the list is another option.
- The time-travelling debugger is cool to show off but has some limitations that make it less useful in practice. If the Msg is long it gets cut off and there's no way to see the whole thing. There's no way to exclude or filter messages, if you have timer running the message list quickly fills up and it is difficult to find the Msg you want.
- There is little published information on what is coming down the pipeline, timelines for bug fixes, features, etc
This final one hasn't been a big problem in practice, but the prohibition on effect managers and native code in the community leads to teams all over the place reimplementing the same thing (e.g. interfacing with LocalStorage). It has never been possible to publish code using ports or native code to Elm's package manager, which I think is a good thing, but 0.19 also removed the ability to compile them locally without forking the compiler. I think I am in a very small minority in the community that thinks that effect managers are not evil and can be used for good.
The codebase is around 60k LOC for the front-end and we've settled on a few patterns that help with reusability and managing complexity.
- We have moved to a very flat architecture where most things are at the top level of the state tree
- We use web components to wrap up things that are a pain in Elm (like exit animations, fancy text editors, interop with various JS libraries)
- Our reusable components take Configs so that the components are not tied to one Msg type, different pages have to provide hookups for those messages but it allows us to reuse components on different pages pretty easily.
Refactoring with confidence is possible! I have worked on large React/Angular apps where it was nigh impossible to refactor something without breaking a bunch of others things (often without a way to know they are broken aside from a full regression test). Typescript has improved things quite a bit, but it can't give you the same guarantees as Elm can.
As for difficulties we've run into:
- The virtual dom diffing slows down as the number of nodes grows, for our live chat we can have thousands of people chatting at once and diffing between the previous/next set of nodes can easily exceed the time we have for the next frame. We've taken to reducing the scrollback available in chat, virtualizing the list is another option.
- The time-travelling debugger is cool to show off but has some limitations that make it less useful in practice. If the Msg is long it gets cut off and there's no way to see the whole thing. There's no way to exclude or filter messages, if you have timer running the message list quickly fills up and it is difficult to find the Msg you want.
- When we were on 0.18 compile times were a large source of frustration, we ended up using a forked version of the compiler to improve things a bit, I wrote about it here https://medium.com/@antewcode/faster-elm-builds-e0669580ee67.
- There is little published information on what is coming down the pipeline, timelines for bug fixes, features, etc
This final one hasn't been a big problem in practice, but the prohibition on effect managers and native code in the community leads to teams all over the place reimplementing the same thing (e.g. interfacing with LocalStorage). It has never been possible to publish code using ports or native code to Elm's package manager, which I think is a good thing, but 0.19 also removed the ability to compile them locally without forking the compiler. I think I am in a very small minority in the community that thinks that effect managers are not evil and can be used for good.