• Как Ionic 2 помогает мне вникнуть в angular 2
    0

    Светлое будущее гибридной разработки на JS для меня выглядит так:


    • TypeScript как язык (статический анализ это круто)
    • Redux and friends для управления состоянием (помойка документации, примеров, best-practice и инструментов разработчика). На нем пилим ядро бизнес-логики, framework-agnostic
    • React-native для мобильных устройств.
    • your-framework-of-choice для фронта, с поддержкой серверного рендеринга.

    Есть пара сравнительно крупных проектов на Ionic 1, в каждом около ~20 cordova-плагинов, push-уведомления, universal links.
    Впечатления плохие.
    Во втором чуть получше — без digest-циклов, человеческий роутер, но все те же лагающие события, запинающиеся анимации.
    Писать на cordova новый проект не хочется, это постоянная боль.


    У RN свои приколы, конечно, но с ними можно мириться, в конце концов переписать лагающие компоненты на натив.

  • 10 особенностей Webpack
    0
    К пункту 4:
    file-loader позволяет передать свой собственный publicPath через параметры, отличный от того, что в output. Таким образом можно все картинки в production-режиме закинуть на отдельный сервер.
    Более того, в качестве publicPath можно даже функцию передать, чтобы динамически url генерить.
    Отсюда совет — читайте исходники лоадеров, в них много всего интересного.
  • Клон Trello на Phoenix и React. Части 1-3
    +1
    Да brunch же!
  • Когда мы написали сотое API мы поняли…
    +2
    Жаль, что не рассказали относительно того, как именно вы версионируете API на уровне кода.
    Под каждую версию API держите свою ветку?
    Или поддерживаете все версии внутри одной кодовой базы?
  • Порог вхождения в Angular 2 — теория и практика
    –2
    Какая у вас основная специфика работы? Frontend / backend? Как долго вы с Ангуляром знакомы? Судя по вашим эмоциям относительно Ангуляр 2 вы с первым не работали.
  • Порог вхождения в Angular 2 — теория и практика
    +6
    Потому что шаблоны в ангуляре декларативные.
  • Fallback-действия в ES6 Promise
    +1
    Можно еще вот так делать. Что, кстати, и рекомендует делать автор bluebird, из-за преемственности со стандартным try-catch потоком.
    .then(function() { 
      throw "Error";
    })
    .catch(function() {
      return "Fallback";
    })
    .then(function(result) { 
      console.log(result);
      // Получаем fallback
    });
    
  • Angular2 теперь «бета»
    0
    Да, на пару дней опоздала новость, но рад, что таки появилась! Жду не дождусь раскидаться с задачами чтобы плотно свои руки наложить на бету.
  • Создание десктопного приложения с помощью Electron и веб-технологий
    0
    Расскажите лучше, как собирать пакет с приложением, использующим нативные плагины.
    Делал утилиту для просмотра точек на карте Google Maps, точки грузил из SQLite. Для SQLite расширение собирается через node-gyp, вот я, помню, попрыгал. Слава богу нужно было только под одну платформу.
  • Gulp: как я проект для production собирал, livereload запускал и перехват ошибок делал
    0
    Еще интересный вопрос — есть у вас 10 вендорных библиотек. В каждой по css-файлу. В каждом css-файле ссылки на изображения и шрифты. Где-то шрифты лежат в ../fonts, где-то в ./fonts, где-то прямо в ./, то же самое с картинками.
    Как будете собирать весь вендорный css в один файл, чтобы пути не поломать?
  • Gulp: как я проект для production собирал, livereload запускал и перехват ошибок делал
    0
    Ок, а что будет происходить, если вы файл удалили? Сначала собрали с ним, потом решили переименовать. Или совсем он вам не нужен. Что будет в этом случае?
  • Gulp: как я проект для production собирал, livereload запускал и перехват ошибок делал
    +2
    gulp.watch при изменении любого файла будет полностью пересобирать скрипты. При 2-х файлах это нормально. А если файлов 100? А если каждый из них прогоняется через babel? Инкрементальная сборка маст хев.

    livereload стили применяет также с перезагрузкой страницы? Применение новых стилей без перезагрузки страницы маст хев.

    И да, пересаживайтесь на webpack (говорю, как человек, который долгое время сидел на gulp)
  • Простые Задачи и Функционально-Блондинистый Подход
    0
    Возможно это мне так запомнилось. Но ООП и Ruby по сравнению с ФП там с гулькин нос.
  • Простые Задачи и Функционально-Блондинистый Подход
    0
    По функциональному программированию в целом на Coursera есть прекрасный курс Programming Languages.
    Его огромное преимущество в том, что он не учит какому-то конкретному языку, а в большей степени посвящен концепциям (иммутабельность, pattern matching, каррирование и.т.д) функциональных языков и почему это хорошо.
    В качестве основного языка там используется ML, полученный опыт легко переносится на любой функциональный язык.
    К сожалению свежих сессий не предвидится, но я нашел канал на ютубе, где выложены все лекции. www.youtube.com/channel/UCzMlECXd856E028HnSYExOQ
    Также на github можно легко найти репозиторий с домашними заданиями.
  • По стопам Meteor, или велосипедируем реактивность
    0
    Модели ($scope) в AngularJS работают через dirty-checking. Это одна из причин, почему его так любят лишний раз пнуть.
    В Angular2 будет поддержка реактивности и иммутабельных данных.
  • Использование ES6 в AngularJs 1.x со сборкой Browserify+Babel
    0
    Это фишка ngAnnotate плагина. Он есть, в том числе, в виде процессора browserify.
  • Использование ES6 в AngularJs 1.x со сборкой Browserify+Babel
    0
    Я у себя классы сделал как-то так:
    export default class Injectable {
      constructor ($injector){
        this._$injector = $injector;
      }
    
      di (){
        var args = _.map(arguments, _.clone);
    
        if(args.length == 1){
          return this._$injector.get(args[0]);
        }
    
        if(args.length > 1){
          return _.map(args, function(arg) {
            return this._$injector.get(arg);
          }, this);
        }
      }
    }
    
    export default class NgController {
      constructor ($scope, $injector){
        this._scope = $scope;
        this._$injector = $injector;
    
        this.log = this._$injector.get('$log');
      }
    
      /**
       *
       * @returns {...String} dependency
       */
      di (dependency){
        var args = _.map(arguments, _.clone);
    
        if(args.length == 1){
          return (this._resolves.hasOwnProperty(args[0]) && this._resolves[args[0]]) ||
            this._$injector.get(args[0]);
        }
    
        if(args.length > 1){
          return _.map(args, function(arg) {
            return (this._resolves.hasOwnProperty(arg) && this._resolves[arg]) ||
              this._$injector.get(arg)
          }, this);
        }
      }
    
      /**
       * @param {String} dependency
       */
      resolve (dependency){
        return this._$injector.get('$state').$current.locals.globals[dependency];
      }
    }
    
    


    Использую так:
    export default class MyController extends NgController {
      /** @ngInject */ constructor($scope, $injector) {
        super($scope, $injector);
        var [MyService1, MyService2] = this.di('MyService1', 'MyService2');
        MyService1.doSomething();
    
        var data = this.resolve('preloaded'); // Вытаскивает данные resolve-секции роутов. Использую ui.router
      }
    }
    


    Все-таки основное преимущество классов в ES6 это как раз наследование без костылей, не использовать его как минимум странно.
    Именно поэтому сервисы я не стал делать классами — попробовал, да мороки больше, не возникало кейсов, где их надо наследовать.

    P.S. Ну и ngAnnotate наше все, прекрасно работает с /** @ngInject */ constructor() {}
  • 40+ полезных инструментов для разработчика приложений под Android
    +2
    Платформа для создания многоплатформенных приложений.

    Это BaaS обычный.
  • Директива AngularJS для запоминания e-mail
    0
    Версия с поддержкой ngModel. Писал навскидку, мог где-то ошибиться.
    Также поддержка интерполяции внутри атрибута и сохранение в куку, только если введенный текст — email.

    (function() {
        var app = angular.module('habr-demo-app', []);
        
        app.directive('habrRememberInCookie', habrRememberInCookie);
        
        function habrRememberInCookie($interpolate) {
            function link(scope, element, attrs, ngModel) {
                var cookieName = $interpolate(attrs.habrRememberInCookie)($scope); 
                if(ngModel) {
                    if(!ngModel.$viewValue) {
                        ngModel.$setViewValue($.cookie(cookieName));
                    }
                    ngModel.$viewChangeListeners.push(function(value) {
                        if(!ngModel.$error.email){
                            setCookieValue(value);    
                        }
                    }); 
                     
                    return;  
                }
    
                if(!element.val()) {
                    var savedValue = $.cookie(cookieName);
                    element.val(savedValue);
                }
                
                element.on('change', function(event) {
                    var newValue = element.val();
                    setCookieValue(newValue);
                });
                
                function setCookieValue(value) {
                   $.cookie(cookieName, value, {expires: 360}); 
                } 
            }
            return {
                restrict: 'A',
                require: '?ngModel',
                link: link
            };
        }
    })();
    
  • Язык программирования Crystal
    0
    Некисло, быстрее Go, на уровне Rust. Спасибо за ссылку!
  • Язык программирования Crystal
    +4
    Анонса на Хабре я не нашел.
  • Язык программирования Crystal
    +8
    Для новости поздно, согласен. Для анонса языка на Хабре нормально.
  • 10 полезных фреймворков, о которых нужно знать разработчику
    +1
    Touchstone.js на стадии прототипа. Зачем он тут?
  • Еще один способ узнать, кто залогинен на сайте, используя faye + redis
    0
    Авторизацию для faye делать не стали?
  • Ionic framework. Обзор экосистемы
    0
    Вопрос про то, как заставить ion-nav-back-button показываться вне зависимости от того, есть в текущем стеке навигации история или нет.
  • Ionic framework. Обзор экосистемы
    0
    Не, там дело не в роутере. С роутером как раз все в порядке — они ui.router используют.
    У Ионика своя система управления стеком навигации, потому что, например, в приложении с табами для каждого таба будет отдельный стек навигации и просто браузерная история тут не подходит.
  • Ionic framework. Обзор экосистемы
    +1
    В ионике без костылей пока невозможно сделать нормальную навигацию вверх по предполагаемому стеку иерархии вьюх, если приложение инициируется на вложенном стейте. Очевидный пример — открытие приложения по тапу на push-уведомлении.
    Допустим, нам надо перейти в диалог, а из него выйти в список диалогов, из которого можно выйти на дашборд. Когда мы начинаем с дашборда и идем вглубь по стеку, все хорошо. Ионик нам покажет кнопочку «Назад», потому что он следит, откуда и куда мы переходим. Но вдруг мы открылись сразу на диалоге! Ионик ни ухом ни рылом, стек навигации пустой. Казалось бы — чего проще: если стек пустой, по кнопке «Назад» идти на некий стейт по-умолчанию. «Гладко было на бумаге, да забыли про овраги» — системная, иониковская кнопка «Назад» показывается только при наличии в стеке навигации «предыдущей» вьюхи, и при пустом стеке она не покажется, даже если ее «форсить» с помощью $ionicNavBarDelegate.showBackButton. Ок, давайте сделаем свою кнопку «Назад» — можно. Только вот системная имеет свои хитрые стили и анимации. Например, умеет под платформы сама подстраиваться.
    Открывал им feature, но они решили, что и так хорошо.

    Вторая интересная история — с картинками. Как они пишут (и что подтверждают полевые испытания), установка src для img на iPhone 6 вызывает лаг 50-200ms. А у них скролл запилен на JS. А трэд общий. Что происходит при списке из 30 элементов с картинками — можно себе представить.

    Пытаются решить двумя способами: загружая картинки через WebWorker и устанавливая вместо ссылки сразу base64, и используя нативный overflow-scroll вместо реализации на JS. С первым вариантом все еще есть вопросы, потому что с base64 все равно есть лаг, хоть и поменьше. Нативный скролл пока только для Android, потому что прикрутили (слава богу) Crosswalk, а iOS нужные события пока не поддерживает.

    История с картинками становится еще хуже, когда хочется использовать картинки в элементах collection-repeat (это список, который переиспользует элементы DOM при скролле). Картинки лагают, список дергается как эпилептик.
    Более того, раз элементы переиспользуются, картинки выкидываются из кеша браузера и при повторном появлении элемента с ранее отображавшейся картинкой, грузятся заново. Поэтому в случае с collection-repeat только base64.
    А использовать его охота уже при величине списка элементов в 100.

    Ну и всякое по мелочи, но может быть это мой 4s уже старичок. В десктопном браузере все «как по маслу», как же иначе.

    Будем надеяться, что до релиза решат вопрос хотя-бы с картинками. А в целом мне он нравится, наверное, потому что я давно с ангуляром кувыркаюсь.
  • Angular 2.0.0-alpha для тех, кто не в силах ждать
    0
    А я как-то подсел на webpack, gulp-ом теперь только его билды запускаю.
    Ладно, попробую на досуге, может чего выйдет.
  • Angular 2.0.0-alpha для тех, кто не в силах ждать
    0
    Fesor, а ты не встречал гайдов как приготовить эту альфу с webpack-ом?
    И обязательно ли связываться с traceur'ом чтобы всю эту кухню запустить или они его используют потому что гугл?
    А то я тоже последнее время на бабеле с webpack, хотелось бы как-то в этой среде все это запустить для «попробовать».
  • Приятная сборка frontend проекта
    0
    main-bower-files выдает файлы из пакетов, уже отсортированных согласно дереву зависимостей («dependencies» в bower.json пакета).
    Но еще один просто огромный плюс main-bower-files это то, что он может использовать секцию «overrides» в bower.json, чтобы переопределить описание установленного пакета.
    Вот пример:

    "dependencies": {
      "angular": "1.3.13",
      "jquery":"1.2.2",
      "some-another-package": "0.0.1"
    },
    "overrides": {
      "some-another-package": {
        "dependencies": {
          "jquery": "*"
        },
        "main": {
          "development": ["some-another-package.js"],
          "production": ["some-another-package.min.js"],    
        }
      }
    }
    


    Предположим, что пакет some-another-package использует jquery, но в зависимостях у него он не прописан.
    Тогда при обработке main-bower-files его файлы могут выпасть перед файлами jquery и будет у нас красная консоль.
    Мы принудительно указываем ему зависимость от jquery и также можем указать разные файлы пакета для разных версий сборки (версию сборки можно указать при вызове mainBowerFiles() в скрипте.

    И исходя из всего вышенаписанного открывается еще одна невиданная доселе возможность: указать в качестве зависимости любой файл из git-репозитория, впоследстии описав его зависимости, после чего он будет обработан mainBowerFiles() и включен в проект в правильном месте. Вот «живой» пример:

    "dependencies": {
       ...
      "flot-splines": "https://raw.githubusercontent.com/AMKohn/flot/master/jquery.flot.spline.js",
       ...
    },
    ...
    "overrides": {
      "flot-splines": {
        "main": [
          "index.js"
        ],
        "dependencies": {
          "flot": "*"
        }
      }
    } 
    


    Само собой, это грязный трюк — завтра реп могут благополучно грохнуть, но иногда он выручает просто безмерно.
  • Пишем с нуля квест на ASP.NET 5 (vNext) и Angular.js
    –2
    Пара вещей, которые меня немного, ну скажем, удивили (?)

    Я, когда пришел в ангуляр, сам некоторое время делал глобальный конфиг, схему роутов и все это заталкивал в один module.config()
    Но через какое-то время пришло озарение, что этот config можно в любом месте делать. Он же как queue, просто добавляются новые шаги в конфигурирование модуля. С тех пор все конфигурации рядом с объектами, которым они принадлежат. Вот пример (правда это из свежего проекта, там 6to5 и ui.router но сути не меняет):

    import {OverviewController} from './controllers/overview_controller.js'
    import {PubNub} from '../../pubnub/index.js'
    export var OverviewPage = angular.module('dashboard.pages.overview', [PubNub.name, 'ui.router']);
    
    OverviewPage.config(function($stateProvider){
      $stateProvider.state(
        'app.dashboard.overview',
        {
          url: '/overview',
          resolve: {},
          views: {
            '@app.dashboard': {
              templateUrl: 'templates/pages/overview/index.html',
              controller: OverviewController,
              controllerAs: 'owCtrl'
            }
          }
        }
      )
    });
    
    
    

    Т.е. у нас во всех отношениях обособленный кусок приложения. Теперь мы вольны подключить объявленый модуль в основное приложение и у нас волшебным образом появится нужный роут. Само собой, модули, объявляющие родительские стейты, тоже должны быть подключены, но это уже вотчина ui.router.

    Второе это

    mainQuestSvc.submitAnswer().get({ token: vm.userToken, taskNumberString: vm.taskId, answer: vm.answer }, function (result) {
                    if (result) {
                        if (result.isAnswerRight) {
                            ...
                            mainQuestSvc.Statistics().get({ token: vm.userToken }, function (result) {
                                if (result && result.ok === "OK") {
                                    vm.watched = result.watched;
                                    vm.done = result.done;
                                } else {
                                    alert('error');
                                }
                            });
                        ...
                    }
                });
    


    Такое, да в контроллере, да без промисов…

    image
  • Еженедельник io.js, 6 февраля 2015
    +1
    В официальном канале проекта на гиттере народ пишет, что вовсю использует. Некоторые даже получают прирост производительности.
    Пишут, что as stable as node v 0.12
  • Еженедельник io.js, 6 февраля 2015
    0
    Никак не могу найти информацию о стабильности.
    Ранее на главной странице проекта была отметка о статусе проекта, сейчас ее нет. Можно ли считать текущую версию стабильной?
  • Нетрадиционный обзор AngularJS
    0
    Вам, безусловно, виднее.
  • Нетрадиционный обзор AngularJS
    –10
    God-object в виде angular

    God-object в виде Yii, Rails «впишите тут свой фреймвора» вас также не устраивает?
    Совершенно уродский синтаксис директив, с чем связан высокий порог входа для написания директив

    В чем он уродский? Или вы не разобравшись с compile, pre-link, post-link, scope transclusion, directive controller, controller require решили забить и обозвать его уродским?
    А еще и не все понимают сам DI

    Что там можно «не понять»?! Это дело одной недели.

    Вам надо было просто написать «Ой, все», всего два слова, а смысла столько же.
  • Нетрадиционный обзор AngularJS
    0
    С чем конкретно вы боретесь, что вызывает недовольство? Хотя бы пункта три.
  • Нетрадиционный обзор AngularJS
    –6
    … а караван идет.
  • Горизонтальное масштабирование websocket-ов на Ruby
    0
    Что случится, когда сервер перестанет вывозить N одновременно подключенных клиентов? Нужно будет добавить еще один websocket-сервер.
    А взаимодействовать между собой они будут через Redis. Что-то мне подсказывает, что сервер WebSocket уткнется в свой потолок гораздо раньше, чем Redis.
  • Горизонтальное масштабирование websocket-ов на Ruby
    0
    Там чуть сложнее, вот пример ключей, которые он хранит:
    1) "/clients"
    5) "/channels/time"
    7) "/clients/j6hb00g9ta8d8y8b9o48hmi4b2br0bh/channels"
    9) "/channels/user/registered"

    Т.е. общий пул соединений (клиентов), каналы, на которые подписан конкретный клиент, и очереди для каждого используемого канала.
  • Горизонтальное масштабирование websocket-ов на Ruby
    0
    Клиент-клиент как раз нет, количество каналов будет равно количеству клиентов.
    Публикуете в канал /user/:id, на который подписывается пользователь с :id, в сообщении присылаете id пользователя-отправителя.

    Ну и огромный плюс faye — он не ограничен одним websocket.