我们为什么以及是如何从 Angular.js 迁移到 Vue.js? 已翻译 100%

oschina 投递于 2017/10/19 18:10 (共 9 段, 翻译完成于 10-23)
阅读 15816
收藏 52
5
加载中

As I'm writing this, we've just removed the last line of AngularJS code from our application codebase, ending a 4-month non-intrusive effort to migrate our application from AngularJS to VueJS. In this post, I'm going to share our experience going through the process.

Some Background

Our application (Holistics.io) is a SQL-based Business Intelligence (BI) Platform written with Rails, Sidekiq, PostgreSQL and AngularJS. Our Rails app started in late 2013 as a simple app with jQuery and AngularJS. We used AngularJS mainly for the following features/functionalities:

  • View model binding (controller, view + template engine)

  • Dependency Injection (services, factories, directives)

  • Angular 3rd party components (uib-modal, ui-select, ...)

The rest are mostly in-house, custom JavaScript.

已有 2 人翻译此段
我来翻译

Our Problems with Angular

As our application grew, these are the problems we're facing with AngularJS:

  • Rendering Performance: As a data tool, a lot of the time we have to render a large table of data, and rendering them with AngularJS yield pretty bad performance.

  • Angular documentation is bad: This isn't a big deal until it is. The more we work with AngularJS, the more we realized that their documentations are really difficult to comprehend.

  • Two-way data flow makes handling logic very difficult, both in term of writing components, as well as writing view controllers. This is perhaps the most important reason of all.

Considering Different Frameworks

Before making a decision, we took a hard look at our different options:

Angular 2

We did spend some time looking into Angular 2. And to us, Angular 2 is somehow even more confusing than Angular 1. There are too many new changes (TypeScript), new template syntaxes, etc that we felt didn't really address our core problems. Furthermore, the migration path from v1 to v2 felt a bit fuzzy to us at the time.

已有 1 人翻译此段
我来翻译

ReactJS

We took a hard look into ReactJS. While we really liked the philosophy and the ecosystem, the biggest thing that struck us is we couldn't figure out a clear, clean, gradual migration path that doesn't stop us from supporting new features for 3-4 months.

AngularJS follows html-based templating system, while ReactJS is JSX, and we couldn't figure out a way to let both of them live nicely together during the migration.

Another minor, subjective reason is, I found JSX rather lengthy compared to HTML-based templating.

EmberJS

EmberJS is the framework for web applications, not a JS library, we would have to rewrite the entire thing in EmberJS.

已有 1 人翻译此段
我来翻译

Why We Went With VueJS: Incremental Migration

There are a combination of reasons that we chose VueJS in the end, but the biggest and most defining factor for us is: we saw a clear, incremental migration path to VueJS without disrupting our development roadmap. In fact, I bet none of our customers ever notice any visible changes at all during the whole period, they wouldn't know which page they visit is Angular-based, which page is VueJS-based.

Vue took the similar component-based, props-down-events-up approach of ReactJS, yet surprisingly similar to AngularJS in term of templating engine. It feels like the right mix of AngularJS and ReactJS combined. This works perfect for us, since we have a lot of AngularJS templates, and our main problem is the logic complexity introduced while using Angular components.

已有 1 人翻译此段
我来翻译

In fact most of the time what we needed to do was to change our code from ng- to v-. This is brilliant!

The more we dug into it, the more we realized we're making the right choice that solved all our earlier problems: great performance, single file component, very clean code structure, slots, etc.

Also, during the migration process, because of the way Vue structures (one way data flow, component-based), it forced us to rethink and refactor rather poorly written code, thus greatly simplify our code logic.

One last point that I'd like to mention, is I find VueJS documentations extremely well-written and well-structured. This is another major feature why we chose VueJS. When I was first introduced about Vue, I spent 30 minutes reading its documentation, and felt immediately compelled to try out.

已有 1 人翻译此段
我来翻译

How We Incrementally Migrated:

Below are simple steps we took for the migration (note that this is related to our context of running a Rails app, if you're not using Rails, some of these might be different):

1. Convert AngularJS controllers' logic to VueJS

For an incremental migration strategy to work, we do the minimum amount of work needed to introduce VueJS to our code. Thus we start by changing our standard AngularJS controller + template files and introduce Vue to it:

// user_edit_controller.js.es6`
import Vue from 'vue'

app.controller('UserEditCtrl', ['$scope', '$http', 'Ajax', 'Util', 'Modals',  
  function ($scope, $http, Ajax, Util, Modals) {
    let vapp = new Vue({
      el: '#v-wrapper',
      components: {
          ...
      },
      data: {
      }
    });
  }
]);

<!-- `users/edit.html.erb` -->

<div ng-controller="UserEditCtrl">  
  <div id="v-wrapper">
    <!-- vuejs logic goes here... -->
    <input v-model="username" placeholder="Username" />
    ...
  </div>
</div>

This allows us to introduce Vue logic into our app, without changing any of the underlying app's frontend structure. It greatly helps us mitigate risks of making mistakes, as we can just quickly spend 1-2 hours converting a small portion of AngularJS to VueJS, test and deploy, without having to worry of causing regression bugs.

已有 1 人翻译此段
我来翻译

2. Convert AngularJS services to ES6 modules

First, we need to find a replacement for $http service, which we use the most among the AngularJS. For this, we simply change to using axios. We don't use $http$directly but build a wrapper abstraction around it, so changing it is pretty simple.

Then, we have a lot of AngularJS services defined as:

// users.js
app.service('Users', ['$http', 'Ajax',  
  function ($http, Ajax) {
    this.create = function(user) {
      // ...
    }
  }
]);

We simply change them to using ES6 class:

// users.js.es6
export default class Users {  
  static create(user) {
    // ...
  }
}

If there's still Angular code in other controllers using these services, we clone the services to using ES6 Class, and keep the old Angular copy until no other Angular code uses this anymore. This duplicates our code for a while, but we just need to be careful about this, and make extensive comments in the code to link between the 2 copies.

已有 1 人翻译此段
我来翻译

3. Replace AngularJS controllers with VueJS components

After doing the above 2, some AngularJS controllers can be completely moved over to using VueJS, so similar to step 2 above, we swap out the app.controller() definition with using ES6. But this time, we then use Vue's Single File Component:

File: user_edit.vue

<template>  
  <div>
    <!-- vuejs logic goes here... -->
    <input v-model="username" placeholder="Username" />
    ...
  </div>
</template>

<script>  
import Users from 'users.js.es6'  
export default {  
  data: {    
  },
  methods: {   
  },
  mounted() {
    // initializing
  }

};
</script>

4. Add mounting entry point for Rails controller/view

By default, on every rails page load it will render the view. With the above Vue's Single File Component, we then change our Rails view users/edit.html.erb file to:

<div class="v-user-edit">  
  <user-edit></user-edit>
</div>

And then put a code to mount it to the correct Vue component when the page loads:

import UserEdit from 'user_edit.vue'  
let vueConfig = {  
  el: '.v-user-edit',
  components: {
    UserEdit
  }
};
new Vue(vueConfig);

In practice, the above JS code is abstracted into reusable function to be called in different pages.

已有 1 人翻译此段
我来翻译

Conclusion

We finished migrating our framework late September 2017, about 4 months of non-intrusive work (we continue adding other features while working on the migration). In fact we didn't really put the migration at our top priority, whenever we need to make a change that touch old Angular code, we first converted it to Vue, and then make our change.

After the migration, now we have achieved:

  • Very clean code and modular (component-based), VueX and Vue Store; these greatly increased programming productivity

  • No more complex logic

  • Enhance UI performance

This is not to say Vue is the best, it simply worked best for our specific case: an Angular-heavy application that hits some limitation due to inherent design nature of Angular, and Vue filled that gap perfectly for us, with a very natural, incremental path of migration.

What are your thoughts? Do share with us in the comments below. Would love to learn more about your case!

已有 1 人翻译此段
我来翻译
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
加载中

评论(44)

飞龙博客
飞龙博客
不管 冒出啥框架,要用啥框架,我只用自己的框架。
李中凯
李中凯
有谁知道具体怎么做的吗?Angular 6 里怎么用Vue单文件组件,编译是怎么做到的?
Ryvn
Ryvn
看起来不错
星光似霰
星光似霰

引用来自“猪面”的评论

在用Angular4,后台应用中最常出现的table用了Primeng的datatable,功能丰富,但,性能真的很一般,有碰到类似问题的同仁吗?
用的bs-table,性能还可以
答复哈
答复哈
这个标题让我看愣了一下~
獜彝
獜彝

引用来自“华丽的转身”的评论

大道至简。一个项目中除了牛B的技术框架外,其实效率、可维护性、往往是非常重要的,有多少团队的技术人员都是牛B的高手,几番人员流动后,谁知道代码会变成什么样子,谁知道又是什么样的人接口,又有多少公司有非常完备的代码检查管理。瑞士军刀不可能适应所有项目,我暂同博主!每种技术的诞生都有其优势,技术要为项目服务,而不是项目去追求技术,找适合自己项目的技术还是正道。
我不听,我不听。反正是你们的问题,ng天下无敌
a
aazzoo

引用来自“aazzoo”的评论

一年之后。我们为什么以及如何从vue迁移至angular 的。ps:你迁移就迁移呗。没必要贬低另外一个 挑起战争。ts 难学吗?怎么不说自己菜。连ts都学不好.还是算了别编程了; ts 的强类型可以在避免一些问题,ts不会像es6 es7 安装一堆的babel依赖。还可能依赖问题找半天; 而且ts 团队协同的时候简直爽的不要不要; 面向接口编程。

引用来自“xmut”的评论

你好像喷错了,Vue也支持TS啊 😃😃
傻不拉几的。自以为自己很高深。
a
aazzoo

引用来自“aazzoo”的评论

一年之后。我们为什么以及如何从vue迁移至angular 的。ps:你迁移就迁移呗。没必要贬低另外一个 挑起战争。ts 难学吗?怎么不说自己菜。连ts都学不好.还是算了别编程了; ts 的强类型可以在避免一些问题,ts不会像es6 es7 安装一堆的babel依赖。还可能依赖问题找半天; 而且ts 团队协同的时候简直爽的不要不要; 面向接口编程。

引用来自“xmut”的评论

你好像喷错了,Vue也支持TS啊 😃😃
你那只眼睛看到我说vue不能用ts 了?
我没说vue 不能用ts 吧。你不识字吗?我是说题主因为ts 放弃angular;动不动说别人是喷子? 你才是吧。看都不看我说的什么
_console
_console
自己觉得那个好用就用那个呗!
Aschrius
Aschrius

引用来自“dexterz”的评论

做BI的,同样是AngularJS,typescript开发的power bi甩你几百条街

引用来自“xmut”的评论

你是不是喷错了,VUE也支持TS啊 ,这不应该成为一个喷点 😁😁😁
好像近期才支持的?
返回顶部
顶部