Seems like quite some time have passed since the last post. That's because in the end of the last month I was busy with passing the last exams. And this month I've finally started to do the GUI. First off, I thought out the structure of the application, decided which tools to use and which not by weighting all the pros and cons, and wrote some code. Unfortunately, I haven't managed to run the working demo yet, but I'm close to this. In this post I'd like to talk about three things: structure of React/Redux app, managing CSS styles in the component and the choice of code editor. So, let's start.
Although I'm familiar with both React and Redux and done some stuff with them, but to be honest, I've never done complex web applications with this stack and that's why sometimes I'm not sure what's the right way to do some things. For example, I've encountered a problem that somehow I can't build the UI gradually, step-by-step. Just to start writing code I needed to fully outline the application structure, its logic and data flow, because it seemed to me that every change to it later will lead to significant code rewriting. I checked out documentation and found out that it's actually not far from being truth. It's said there that designing state shape should actually be done "before writing any code". And for complex applications it can be really tricky. So, I guess it's more like a consequence of Redux approach, luckily it should be done only once. Generally, I thought out the application logic, then based on it I created all actions needed for this, then I designed some middlewares to deal with asynchronous actions, then I wrote reducers to handle these actions and only after that I created some views (components). By the way, I made use of
immutable.js library, because it's perfectly match Redux and because it's just super cool. Basically, the core logic of GUI is ready and now I need to make it running and tighten it up.
In the proposal to this project I said that a single CSS file will be enough, but when I started working on the GUI I decided to put a little more thought into this (probably because of curiosity) and in the end I reverted to the point I started from :) But now I have some good arguments. Let's start with the obvious problems that CSS have: bad encapsulation and terrible reusability. And these things matter in the big projects. Once I was working in the project with huge codebase where even BEM was absent. I needed to take one piece of a page and just paste it to another. This type of task should take merely 5 minutes to finish. But it costed me half a day. That's why encapsulation matters. Moreover, using third-party components can also be entangling due to these problems. There're several options to choose from when you want to deal with them: BEM, CSS Modules, inline styles, Web Components. I considered all of them from the point of writing CSS for a reusable React component. What I tried to achieve is to make component easily cusomizable (through CSS overriding, because CSS is a perfect DSL for this kind of stuff) and avoid collisions with other CSS styles. And since customization was one of the main goals I ditched inline styles immediately (even though they are promoted heavily in the React community). BEM has a lot of boilerplate but it's simple and it works. The point is, it's needed only in big projects with a lot of components (and I have only one). CSS Modules/ICSS is a very interesting approach, but it based on adding random hashes to CSS classes which makes customization very hard. It cures symptoms, not the problem itself. So, I decided that the most natural approach is just give the user a simple, plain, good old CSS file to include into his page and override it. To avoid collisions we can use prefixes (I use PostCSS to accomplish this). Of course it doesn't solve the problem with encapsulation. But the most important thing that I've understood from all of this is — I don't need to solve it! It's user who should think of this, not the component distributer. When you're developing a component it's perfectly fine to just have a main file for styles (or a couple of them). I'd rather say it should be done this way. But how the user is supposed to solve the problem with encapsulation by himself? The answer is Shadow DOM. And for the reusability problem (which is more general) it's Web Components. For a long time I was feeling very sceptic about Web Components standard, it seemed overcomplicated to me. But I was wrong. In fact, they solve all of the stated problems without compromising the customization and without changing the way we think about CSS. Also, I thought of Web Components as the competitor of React. Wrong again! They solve completely different problems. Web Components help to reuse parts of application across different projects without breaking the styles and it's their main goal. React on its side helps to build application architecture based on the components model and represent it as the function of data. And they can be easily used together! We can build Web Component using React. We can use Web Components in our React application. That's the point. Of course the browser support of Web Components is not good enough (yet), but I find the idea behind them to be very neat. Well, seems like I dived into this a bit much, but I'm glad that now a have a good understanding.
Initially I decided to use Prism with a bunch of plugins for syntax highlighting. But then @jonasfj suggested to use full-fledged code editor instead (like Ace or Codemirror). And it was a great idea! :) I decided to use Ace, because it's more popular and have all of the needed features: the ability to set breakpoints, readonly mode, specific line highlighting (markers). It'd be nice if it also could focus (i.e. center the viewport) on the specific line, 'cause I left a place for this functionality in the React application. By the way, I found a ready React component for this editor. Unfortunately, it doesn't support
guttermousedown event which I need. I think I'll fork it, add this functionality, and install it directly from my repo with npm (I don't think that PR will be merged as soon as I send it).
- Embed Ace editor
- Launch the demo
- Finish and style the components
- Create the tree view for the sources (instead of a plain list)
- Add support for multiple targets
- Optimize some parts of code where it makes sense
Generally, everything is proceeding according to plan. I guess that the next post I will write when I finish the component and run the demo. Although, reasonable UX for multiple target might have some time.