1

Luoo.net has always been one of my favorite music communities, with a lot of good indie music recommendations that I like and respect for their commitment to music for over a decade. The music software I use on my mobile phone is second only to netease Cloud, but I can only use web pages to listen to the music, so I decided to write a computer client for the music.

New Luoo. Qy V1.0 version after nearly two months of development, each UI has been carefully redesigned, but also increased the user login, synchronous collection and lyrics display (Working) and a large number of functions, the internal code has been completely reconstructed, a lot of optimization; More functions please download after experience:

  • The client can be downloaded in L. Page. China (computer access) and supports macOS, Windows and Linux
  • Client project address: luoo.qy (GitHub)
  • The back-end project address is Luoo(GitHub)

2. Preview/Preview

The design draft:

List of journals:

Journal:

& amp; amp; amp; lt; img data-rawheight=”1181″ src=”https://pic1.zhimg.com/v2-b219579be1ba71ad41885cd583eb226c_b.png” data-rawwidth=”1889″ class=”origin_image zh-lightbox-thumb” width=”1889″ data-original=”https://pic1.zhimg.com/v2-b219579be1ba71ad41885cd583eb226c_r.png”& amp; amp; amp; gt; Singles list:


Singles list:

Now playing :& amp; amp; amp; lt; img data-rawheight=”1181″ src=”https://pic3.zhimg.com/v2-5b9df6b9f58a0a4af00b5f8951a2ba12_b.png” data-rawwidth=”1890″ class=”origin_image zh-lightbox-thumb” width=”1890″ data-original=”https://pic3.zhimg.com/v2-5b9df6b9f58a0a4af00b5f8951a2ba12_r.png”& amp; amp; amp; gt;


Type of music:

& amp; amp; amp; lt; img data-rawheight=”1181″ src=”https://pic1.zhimg.com/v2-85ceed18a2d093b8de5337cd6210edcc_b.png” data-rawwidth=”1890″ class=”origin_image zh-lightbox-thumb” width=”1890″ data-original=”https://pic1.zhimg.com/v2-85ceed18a2d093b8de5337cd6210edcc_r.png”& amp; amp; amp; gt; Settings:


Setting: & amp; amp; amp; amp; lt; img data-rawheight=”1181″ src=”https://pic2.zhimg.com/v2-ba2271a2c142b0e5d745e3e52291164d_b.png” data-rawwidth=”1890″ class=”origin_image zh-lightbox-thumb” width=”1890″ data-original=”https://pic2.zhimg.com/v2-ba2271a2c142b0e5d745e3e52291164d_r.png”& amp; amp; amp; gt; Login:Login:

& amp; amp; amp; lt; img data-rawheight=”1181″ src=”https://pic1.zhimg.com/v2-25cba2b5db0460a1336018d743bfad64_b.png” data-rawwidth=”1890″ class=”origin_image zh-lightbox-thumb” width=”1890″ data-original=”https://pic1.zhimg.com/v2-25cba2b5db0460a1336018d743bfad64_r.png”& amp; amp; amp; gt; Collected Journals:


Collected Journals:

& amp; amp; amp; lt; img data-rawheight=”1181″ src=”https://pic3.zhimg.com/v2-ffaa45728bc506abc43467dc5e30cdfa_b.png” data-rawwidth=”1890″ class=”origin_image zh-lightbox-thumb” width=”1890″ data-original=”https://pic3.zhimg.com/v2-ffaa45728bc506abc43467dc5e30cdfa_r.png”& amp; amp; amp; gt; Collection of periodical songs:


Collection of periodical songs:

& amp; amp; amp; lt; img data-rawheight=”1181″ src=”https://pic4.zhimg.com/v2-10977ffe405201be0c320152201c6df7_b.png” data-rawwidth=”1890″ class=”origin_image zh-lightbox-thumb” width=”1890″ data-original=”https://pic4.zhimg.com/v2-10977ffe405201be0c320152201c6df7_r.png”& amp; amp; amp; gt; Single Collection:


Single Collection:

3. Development

  • Design tool: Sketch
  • Development platforms: macOS Sierra, Windows 10
  • Development tools: WebStorm, PyCharm, SublimeText
  • Client technology stack: Node.js, Electron, Vue, Vuex, NeDB, Webpack, etc
  • Back-end stack: Node, Koa, Python, MongoDB, Urllib, BeautifulSoup, etc

Client project structure:

├── ├.md ├─ Build ├─ db ├─ Main.js ├─ package.json ├─ SRC │ ├─ Components (component directory) │ │ ├ ─ ─ App. Vue components (Root) │ │ ├ ─ ─ Common (general component library) │ │ │ └ ─ ─ Toggle. Vue │ │ ├ ─ ─ HeadBar. Vue (navigation) │ │ ├ ─ ─ Playing. Vue bar (control) │ │ ├ ─ ─ PlayingTrack. Vue (there is) │ │ ├ ─ ─ Singles (Single) │ │ │ ├ ─ ─ in use. The vue │ │ │ └ ─ ─ Singles. Vue │ │ ├ ─ ─ Types. Vue (music type selection) │ │ ├ ─ ─ the User (User) │ │ │ ├ ─ ─ the Login. The vue Login () │ │ │ ├ ─ ─ the User. The vue (User interface) │ │ │ ├ ─ ─ Collection UserCollection. Vue (user) │ │ │ └ ─ ─ UserSetting. Vue (set) │ │ ├ ─ ─ VolView (journal content) │ │ │ ├ ─ ─ VolTrack. Vue │ │ │ └ ─ ─ VolView. Vue │ │ └ ─ ─ Vols (periodicals) │ │ ├ ─ ─ Vol. Vue │ │ └ ─ ─ Vols. Vue │ ├ ─ ─ index, js (rendering process entrance) │ └ ─ ─ store (state management) │ ├ ─ ─ Actions. Js │ ├ ─ ─ getters. Js │ ├ ─ ─ index. The js │ ├ ─ ─ mutations. Js │ └ ─ ─ state. The js ├ ─ ─ the static (client introduced by the static file) │ ├ ─ ─ dist (rendering process packaging) │ │ └ ─ ─ index. Build. Js │ ├ ─ ─ fonts (font) │ ├ ─ ─ HTML (rendering process entry file) │ ├ ─ ─ js (main process required documents) │ │ ├ ─ ─ autoUpdate. Js (automatic hot update) │ │ ├ ─ ─ Config. Js (user profile) │ │ ├ ─ ─ the js database operations (processing) │ │ ├ ─ ─ menuTemplate. Js (in the menu bar) │ │ ├ ─ ─ the sync, js (synchronous data) │ │ └ ─ ─ the user. The js (user) │ │ ├ ─ ─ PIC (image) └ ─ ─ style (CSS) ├ ─ ─ the upgrade (hot update automatically download file) ├ ─ ─ the user (user directory) │ └ ─ ─ config. The json (user profile) └ ─ ─ Webpack.config.js (Webpack configuration)Copy the code


4. Technology implementation/Technology

Technology stack

The whole Luoo.qy V1.0 project adopts MVVM mode to realize the complete separation of the front end and the back end is only responsible for responding to the API requests of the front end;

The entire front-end stack moved from React in v0.0 to Vue; The backend technology stack also fully embraces the JavaScript ecosystem, From Python + Flask to Node + Koa (provides API) and Python + Urllib + Beautiful (crawls data) and MongoDB (stores data);

Because V0.0 version did not use state management, making some functions of the implementation of a little cumbersome, but also caused some problems, so the new version of the use of Vue + Vuex combination of course, to achieve front-end state management;

Implementation of user functions

In order to realize the user function, the logon mechanism of the captured user is studied: The server returns a Cookie with a key of “LUOOSESS” on the first visit to the site. When the user logs in, he/she sends a request to “www.luoo.net/login/” with the Cookie and the user’s account and password. If login succeeds, the server will return JSON data containing user information and another Cookie with key “lult”. When the user bookmarks/unbookmarks, he/she sends a POST request to the corresponding API with a Cookie with a key of “Lult”. After the request is successful, the server will return a piece of JSON data to indicate that the operation is successful. In order to obtain user favorites, the crawler idea is adopted to access user favorites page with Node request module and parse DOM to obtain user favorites list. Visit the user.js file for more details;

Automatic updates versus hot updates

There are several auto-update modules available for Electron, but they all feel too cumbersome, so I use a lightweight auto-update module I implemented in another project, Page.qy, to implement incremental and hot updates. Using the principle of file hot replacement, if you only update the render process, you just need to execute webcontents.reload () after the update, and you can even update painlessly without rebooting the software!

Some problems and solutions

In addition, luoo.qy had performance problems during development, so some work was done to optimize it:

  • Every time the Store loads new data, it causes a serious lag. After understanding the principle behind Vue, this is because Vue adds setter and getter methods to every object in the Store to listen for data in response to changes in the data to the view. But when there is a lot of data stored in the Store, doing this for each object takes a lot of time, so it can cause stalling; The Object. Freeze method prevents Vue from adding getters and setters to the Object, and does not directly access data in State. Instead, change only the index. Use Vuex’s getters to access data indirectly;

  • The initial plan was to use route management to implement view switching, but due to the large amount of data in Luoo.qy and the complex view relationship, the DOM will be redrawn every time the view is switched, which makes the view cannot achieve the feeling of “seamless switching”, so we abandoned route management, and then manually implement the view switching: Directly render all required components into the DOM at startup, and then dynamically set CSS transform, transition, z-index and opacity properties. This will not cause DOM redrawing, and CSS animations can be hardware accelerated. The result is a smooth “seamless switching” view; It’s worth sacrificing some startup time and memory;

  • The initial journal search was implemented using the array. filter method, which iterated through an Array of thousands of objects. Each time there was a delay, the main process exposed a method that looked directly into the local database. The Remote module is used in the rendering process to access this method for lookups, greatly reducing the lookups time;

  • The background color of periodicals and singles, etc., is obtained by taking the average color according to the RGB value of the cover picture. Canvas was initially used to achieve this, so each picture loaded will create a new Canvas object, resulting in a large amount of memory occupation, so this task is handed over to the crawler at the back end: The cover image is downloaded and Python’s graphics library, Pillow, is used to calculate the RGB average values of the images during data climbing, which greatly reduces the client memory usage.

  • In order to improve the loading speed of the software, the database files are packed together when the software is packaged. When the software is started, the data in the local database is loaded first, and the data is updated to the server. Then the updated data is stored in the database, which improves the loading speed and reduces the number of server requests.

  • In the previous version, an HTTP request was sent to the server every time data was updated. If a large amount of data needed to be updated, it would consume a lot of time to establish/disconnect the connection. A complete redesign of the server API in the new version combines multiple requests, greatly reducing the number of connections and the time required to update data, and means that servers can respond to more requests more efficiently.

  • Use the CSS rule “Transform: Transale3D (0, 0, 0)” to enforce hardware acceleration to improve scrolling

  • Electron packs out a folder on Windows instead of a single exe file, and with NSIS you can pack all files into a single installation file

5. Q & A

Why React to Vue?

There is no other reason, because the summer internship company needs to use Vue, so I finished luoo.qy V1.0 while learning Vue.

Why switch from Flask to Koa?

Koa is cool! 😎

New features for the future?

Because the official lyrics are not complete and most of the lyrics do not support scrolling, so we are looking for a suitable third-party API to get lyrics, it is not crawler, but there will be! In addition, automatic syncing of favorites to netease Cloud and other functions may be added, please look forward to…

How can I get Bug feedback or suggestions?

Directly open an ISSUE on GitHub or send a private message to my zhihu followers. You can also send me an email at [email protected].

6. Summary

Special thanks to my good gay friend Kylewh for his invaluable guidance and advice on UI and HTTP request analysis! Welcome to GitHub, especially React tech stack!

In addition, welcome to focus on my other project Page. Qy => 🤘 code free site, based on Node.js, React and Electron

So far, luoo. qy v1.0 has implemented all the basic features. Since summer internships are coming soon, the updates may be slow, but luoo. qy will not stop updating anytime soon, stay tuned to ❤️