jiisoft / jii

Full-Stack JavaScript Framework architecture based on PHP Yii Framework v2
MIT License
244 stars 16 forks source link

Будет ли поддержка ES6-7? #16

Closed sergeysova closed 7 years ago

sergeysova commented 9 years ago

Есть несколько предложений по улучшению фреймворка для совместимости с ES6:

импорты: лучше расположить base.controller и base.model не в общем пакете, а например во вложенности. классы: посмотрите как реализует классы сейчас babel

как я бы хотел:


import { Controller } from 'jii/base';

export default class SiteController extends Controller {
  actionIndex() {
    this.render('index', { text: 'Hello World!' });
    // Фреймворк должен сам отправлять данные клиенту
  }
}

LestaD/Jii-Boilerplate-Basic-NextGenJS Сейчас лучше развивать фреймворк в сторону js, так как node.js имеет отличную архитектуру от php, соответственно фреймворк должен иметь свою структуру

sergeysova commented 9 years ago

Также очень хотелось бы иметь поддержку любого шаблонизатора, например Jade По мне он лучше чем ejs:

html
  head
    title=title
  body
    h1=title
    p=content
sergeysova commented 9 years ago

Я перепишу boilerplate, ради примера того, как это могло бы быть реализовано в стиле es6 Результат положу сюда

affka commented 9 years ago

По ES6 было много рассуждений, я пришел к тому, что пока node.js не будет нативно поддерживать es6 формат, перехода на es6 не буду делать.

По мне он лучше чем ejs:

ejs - это чисто расширение файла, чтоб IDE не тупило и понимало js в html. Шаблонизатор сейчас там undercore, но поставить другой - легко, под это есть абстракция.

Я перепишу boilerplate, ради примера

Будет интересно посмотреть, спасибо! Ваш пример в первом комментарии выглядит весьма красиво!

Сейчас лучше развивать фреймворк в сторону js

Из Yii хочется перенимать принципы, подходы. Все не получится, но многое уже миграровало успешно. Тут от языка не все зависит, Yii много чего взял из Ruby, например. Основная фишка Jii - это знакомость API. Поэтому совпадение хочу делать максимально возможное, на сколько это позволяет различие языков и здравый смысл :)

sergeysova commented 9 years ago

@affka да перенимать принципы можно, но всё должно быть в рамках идеологии node.js

sergeysova commented 9 years ago

@affka я готов показать Вам концепт того как может выглядеть Jii в идеале. LestaD/Jii-Boilerplate-Basic-NextGenJS Часть функционала, включая классы уже поддерживается в io.js(node.js) >= 3.0

affka commented 9 years ago

Спасибо, выглядит неплохо. От неймспейсов в таком случае нужно будет вообще отказаться.. хотя вот тут что-то осталось - "className: JiiMysql.Connection," там не должно быть типа import { Connection as JiiMysqlConnection } from 'jii/sql/mysql'; ?

Можно ли без JiiAR, JiiView и прочих переименований сделать? дефисы в названиях пакетов мешают же?

sergeysova commented 9 years ago

@affka на самом деле можно импорты называть как угодно, тут дело вкуса и линтера. В данном концепте я представил куда можно двигаться Jii.

sergeysova commented 9 years ago

@affka хотя если хорошо подумать, то архитектурно, наверно, лучше сделать так:

import Jii, { UrlManager, View, AssetManager } from 'jii';
import { Mysql as JiiMysql } from 'jii/sql';
import { ActiveRecord } from 'jii/base';
import HttpServer from 'jii/server';

То есть поместить общие компоненты в jii, http-сервер выделить в отдельный файл jii/server, в 'jii/base' положить общие компоненты, от которых следует наследоваться, а в 'jii/sql' положить всё что связано с SQL, просто экспортировать под разными именами. В случае поддержки NoSQL сделать точно такой же API как у jii/sql, но для jii/nosql. Туда например Mongo, TingoDB.

sergeysova commented 9 years ago

@affka кстати декораторы из ES7 можно использовать как трейты php php5-traits

trait className {
  private $clsna = '(example)';
  public function className() { return $this.clsna }
}

class BasePlayer {
  use className;
}

$player = new BasePlayer();
$player->className()

function className(cls) {
  if (typeof cls === 'function') {
    cls.prototype.className = function() { return cls.name; }
  }
}

@className
class BasePlayer {
  // code here
}

let player = new BasePlayer();
player.className();
affka commented 9 years ago

http-сервер выделить в отдельный файл jii/server

файл? или папку? Я не особо знаю синтаксис ES6, поэтому хочу уточнить:

import Jii, { UrlManager, View, AssetManager } from 'jii';

это означает, что в пакете лежат файлы index.js (Jii), UserManager.js, View.js, AssetManager.js?

import { ActiveRecord } from 'jii/base';

А это - что в пакете есть папка base и в ней файл ActiveRecord.js?

Я так понимаю, что это преобразуется в var ActiveRecord = require('jii/base/ActiveRecord') ?

affka commented 9 years ago

и еще вопрос - как дела обстоят у IDE, в частности IDEA (WebStorm/PhpStorm) - подсказывает ли он классы, добавляет ли он их автоматом в секцию import, как это он делает с секцией use в php?

affka commented 9 years ago

Ух ты, node.js и io.js уже объединились! Хотя обещали только в 16ом году. Теперь нода поддерживает ES6 - https://new.nodejs.org/en/blog/release/v4.0.0/ Это убирает главный стоппер на перенос Jii на ES6.

ZAYEC77 commented 9 years ago

@affka касательно именно продуктов Jetbrains, они имеют поддержку TypeScript и ES6 классы. Еще знаю, что Visual Studio точно потдерживает TS)

sergeysova commented 9 years ago

@affka Введение в CommonJS Modules:

import name from 'package';

означает

var name = require('package');

Далее вложенные части

import name from 'package/add';

означает

var name = require('package/add')
// внутри пакета под именем package есть файл add.js

далее деструктуризация:

import { foo, bar } from 'package';

это значит что мы импортируем foo и bar из пакета package; чтобы их импортировать из пакета, надо чтобы пакет их экспортировал

// package

export function foo() {
   // any code
}

export const bar = 'special constant or variable';

реально выглядит как-то так:

module.exports.foo = function() {
  // any code
}

module.exports.bar = 'special constant or variable';

!но!

мы не можем получить сразу всё с помощью конструкции импорта по умолчанию:

import all from 'package';

all === {}; // true

для такого нужно экспортировать по умолчанию нужный объект:

export default class World {} // вот оно

export function bar() {}

export const foo = 'const';

импорт всего этого добра будет выглядеть так:

import World, { bar, foo } from 'package';

Кстати, можно импортировать себе не только под именами которые экспортирует пакет:

// yourpackage

export default class Framework {
   constructor(yourconfig) {
    this.config = this.merge(this.defaults, yourconfig);
  }
  // ... 
}

export class DatabaseDriver {
  constructor(drivername) {
    this._driver = this.loadDriver(drivername);
  }
  // ...
}

export function createApplication(configuration) {
  let newapp = new Application(configuration.app);
  newapp.database = new DatabaseDriver(configuration.db);
  newapp.extends(new Framework(configuration);
  return newapp;
}

Допустим, если я буду импортировать класс DatabaseDriver, то в у меня возникнут конфликты имён:

import { DatabaseDriver } from 'thif';
import { DatabaseDriver } from 'yourpackage'

Что делать? — можно импортировать любую часть под нужным именем:

import { DatabaseDriver } from 'thif';
import { DatabaseDriver as YPDBDriver } from 'yourpackage';

// here DatabaseDriver is thif's object
// but YPDBDriver is yourpackage's 

Также можно группировать импорты:

import { DatabaseDriver } from 'thif';
import YPFramework, { DatabaseDriver as YPDBDriver, createApplication } from 'yourpackage';

А теперь что такое деструктуризация на очень явных примерах:

let Obj = {
  name : 'lestad',
  age: 20
}

let { Name, Age } = Obj;

babel трансформирует в старый js:

var Obj = {
  name: 'lestad',
  age: 20
};

var Name = Obj.Name;
var Age = Obj.Age;

Не сильно сложно

sergeysova commented 9 years ago

Да и кстати, лучше не делать никаких globals!

affka commented 9 years ago

Спасибо за примеры! Globals и пишу только в примерах, чтобы было проще въехать разработчику. Сам Jii не регистрирует глобальных переменных.

sergeysova commented 9 years ago

@affka обновил примеры)

sergeysova commented 9 years ago

вот ещё небольшой пример импортов из реального проекта:

import React, { Component } from 'react';
import Modal from 'react-modal';
import Svgo from 'Element/Svgo/ElementSvgo';

import { close, afterClose, PopupList, show } from 'actions/ModalActions';
import { logout } from 'actions/AccountActions';

import WidgetLogin from 'Widget/Login/WidgetLogin';
import ModalCloseButton from 'Widget/Modal/CloseButton';
import WidgetRegistration from 'Widget/Registration/WidgetRegistration';
import WidgetMobileApprove from 'Widget/MobileApprove/WidgetMobileApprove';
sergeysova commented 9 years ago

лучше по возможность отказывать от нескольких фреймворков, вроде lodash и underscore одновременно. Я вот, для объединения объектов использую такую функцию:

/**
 * Deep merge objects
 * @param {...Object} objects Any listed object
 */
export function MergeObjects(...objects) {
  let result = {};
  for (let current of objects) {
    for (let key in current) {
      if (current.hasOwnProperty(key)) {
        if (typeof current[key] === "object" && typeof result[key] === "object") {
          result[key] = MergeObjects(result[key], current[key]);
        }
        else {
          result[key] = current[key];
        }
      }
    }
  }
  return result;
}

Парочка примеров использования декораторов: lestad/es6-decorators

affka commented 9 years ago

я не вижу применения для экспорта набора методов/свойств, у меня в каждом файле по классу всегда. А значит будет всегда типа: import WidgetLogin from 'Widget/Login/WidgetLogin';

где Widget/Login по сути является неймспейсом, а WidgetLogin - названием класса.

affka commented 9 years ago

В Jii сейчас только функционал underscore используется. Для мержа объектов (а он нужен только для мержа конфигов) - я тоже свой метод написал - Jii.mergeConfigs().

sergeysova commented 9 years ago

я не вижу применения для экспорта набора методов/свойств, у меня в каждом файле по классу всегда. А значит будет всегда import WidgetLogin from 'Widget/Login/WidgetLogin';

Так и должно быть, это подход ES6. Вы всегда явно определяете ЧТО хотите иметь в своём файле. В Java (который является родителем JS) сделано именно так:

import com.java.name;

Require all это очень плохая практика. yii2 строится таким образом, что в процессе выполнения подключаются только нужные файлы, а ведь в yii2 файлов тысячи.

sergeysova commented 9 years ago

Вот пример из реального проекта, в котором очень много файлов. А это лишь малая часть

screen shot 2015-09-10 at 13 23 19

sergeysova commented 9 years ago

@affka попробуйте такой редактор как SublimeText. Ответственно заявляю как программист, он очень крут, особенно с большим количеством плагинов.

affka commented 9 years ago

В моей работе Sublime'a будет мало, я PhpStorm юзаю :) Он не идеал, но лучшей альтернативы не знаю. Sublime отличный редактор, и им тоже пользуюсь иногда. Но это не IDE.

Require all это очень плохая практика.

Да, это костыль был, даже скорее временный. В пхп подобный подход был бы проблемным, т.к. пхп каждый раз умирает и часть файлов действительно излишне грузилась бы, а нода загружается один раз и время загрузки не сильно критично. Расход памяти от этого тоже не думаю что сильно увеличивался бы.

Вот пример из реального проекта

а почему *.jsx? Что "х" значит?

sergeysova commented 9 years ago

@affka jsx — формат js включающий поддержку синтаксического сахара для React.js

По поводу require all, не во всех проектах нужна вся мощь фреймворка, ОЧЕНЬ хотелось бы, чтобы фреймворк подгружал только то, что нужно

sergeysova commented 9 years ago

Example of jsx:

import React, { Component } from 'react';

export default class User extends Component {
  render() {
    return (
      <div class="User">{this.props.username}</div>
    );
  }
}
sergeysova commented 9 years ago

Возьмем к примеру, у меня есть проект на express, при старте он занимает около 100Мб в ОЗУ. Если не заходить в админку, и пользоваться только клиент-сайд, то займет памяти не больше 200Мб. НО если полезть в админку, то всё станет интереснее, занимаемая приложением память увеличится до 500Мб.

Так о чём я, если я запускаю уже настроенный проект, я не хочу чтобы он сам по себе загружал ВСЁ! Хочется чтобы только то, что нужно. иначе ужс был б. Если бы не освобождение памяти по требованию, то приложение уже перевалило бы за 1ГБ ОЗУ, а мне нельзя, на вдс и так не много памяти

affka commented 9 years ago

что-то сильно большие расходы памяти у вас для express, но в любом случае согласен, что фреймворк не должен все разом подключать. Учту это, когда буду переписывать под ES6

sergeysova commented 9 years ago

@affka Просто у меня в приложении ОЧЕНЬ много моделей и мало контроллеров/роутов. Пользователю дано редактировать почти всё что он видит.

affka commented 9 years ago

что-то не видно поддержки импортов в node.js - https://nodejs.org/en/docs/es6/ в io.js этого тоже получается небыло?

sergeysova commented 9 years ago

@affka импорты будут не скоро. Но если фреймворк не поддерживает качественные импорты в ES6 это существенный минус. Когда я говорил про es6 я имел ввиду нативное создание классов по месту когда class Foo {} идентично (function(){ function Foo(){}})(). В данный момент в Jii нельзя создать просто класс через Jii.createClass он определяется где-то, но не здесь

affka commented 8 years ago

Задачка для тех, кто хотел es6 - https://toster.ru/q/276621

sergeysova commented 8 years ago

@affka ответ: не нужно смешивать разные подходы

affka commented 7 years ago

Jii перешел на es6 классы и поддержку es6. Тема более не актуальна