Closed sergeysova closed 7 years ago
Также очень хотелось бы иметь поддержку любого шаблонизатора, например Jade По мне он лучше чем ejs:
html
head
title=title
body
h1=title
p=content
Я перепишу boilerplate, ради примера того, как это могло бы быть реализовано в стиле es6 Результат положу сюда
По ES6 было много рассуждений, я пришел к тому, что пока node.js не будет нативно поддерживать es6 формат, перехода на es6 не буду делать.
По мне он лучше чем ejs:
ejs - это чисто расширение файла, чтоб IDE не тупило и понимало js в html. Шаблонизатор сейчас там undercore, но поставить другой - легко, под это есть абстракция.
Я перепишу boilerplate, ради примера
Будет интересно посмотреть, спасибо! Ваш пример в первом комментарии выглядит весьма красиво!
Сейчас лучше развивать фреймворк в сторону js
Из Yii хочется перенимать принципы, подходы. Все не получится, но многое уже миграровало успешно. Тут от языка не все зависит, Yii много чего взял из Ruby, например. Основная фишка Jii - это знакомость API. Поэтому совпадение хочу делать максимально возможное, на сколько это позволяет различие языков и здравый смысл :)
@affka да перенимать принципы можно, но всё должно быть в рамках идеологии node.js
@affka я готов показать Вам концепт того как может выглядеть Jii в идеале. LestaD/Jii-Boilerplate-Basic-NextGenJS Часть функционала, включая классы уже поддерживается в io.js(node.js) >= 3.0
Спасибо, выглядит неплохо. От неймспейсов в таком случае нужно будет вообще отказаться.. хотя вот тут что-то осталось - "className: JiiMysql.Connection," там не должно быть типа import { Connection as JiiMysqlConnection } from 'jii/sql/mysql'; ?
Можно ли без JiiAR, JiiView и прочих переименований сделать? дефисы в названиях пакетов мешают же?
@affka на самом деле можно импорты называть как угодно, тут дело вкуса и линтера. В данном концепте я представил куда можно двигаться Jii.
@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.
@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();
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') ?
и еще вопрос - как дела обстоят у IDE, в частности IDEA (WebStorm/PhpStorm) - подсказывает ли он классы, добавляет ли он их автоматом в секцию import, как это он делает с секцией use в php?
Ух ты, node.js и io.js уже объединились! Хотя обещали только в 16ом году. Теперь нода поддерживает ES6 - https://new.nodejs.org/en/blog/release/v4.0.0/ Это убирает главный стоппер на перенос Jii на ES6.
@affka касательно именно продуктов Jetbrains, они имеют поддержку TypeScript и ES6 классы. Еще знаю, что Visual Studio точно потдерживает TS)
@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;
Не сильно сложно
Да и кстати, лучше не делать никаких globals
!
Спасибо за примеры! Globals и пишу только в примерах, чтобы было проще въехать разработчику. Сам Jii не регистрирует глобальных переменных.
@affka обновил примеры)
вот ещё небольшой пример импортов из реального проекта:
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';
лучше по возможность отказывать от нескольких фреймворков, вроде 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
я не вижу применения для экспорта набора методов/свойств, у меня в каждом файле по классу всегда. А значит будет всегда типа: import WidgetLogin from 'Widget/Login/WidgetLogin';
где Widget/Login по сути является неймспейсом, а WidgetLogin - названием класса.
В Jii сейчас только функционал underscore используется. Для мержа объектов (а он нужен только для мержа конфигов) - я тоже свой метод написал - Jii.mergeConfigs().
я не вижу применения для экспорта набора методов/свойств, у меня в каждом файле по классу всегда. А значит будет всегда import WidgetLogin from 'Widget/Login/WidgetLogin';
Так и должно быть, это подход ES6. Вы всегда явно определяете ЧТО хотите иметь в своём файле. В Java (который является родителем JS) сделано именно так:
import com.java.name;
Require all это очень плохая практика. yii2 строится таким образом, что в процессе выполнения подключаются только нужные файлы, а ведь в yii2 файлов тысячи.
Вот пример из реального проекта, в котором очень много файлов. А это лишь малая часть
@affka попробуйте такой редактор как SublimeText. Ответственно заявляю как программист, он очень крут, особенно с большим количеством плагинов.
В моей работе Sublime'a будет мало, я PhpStorm юзаю :) Он не идеал, но лучшей альтернативы не знаю. Sublime отличный редактор, и им тоже пользуюсь иногда. Но это не IDE.
Require all это очень плохая практика.
Да, это костыль был, даже скорее временный. В пхп подобный подход был бы проблемным, т.к. пхп каждый раз умирает и часть файлов действительно излишне грузилась бы, а нода загружается один раз и время загрузки не сильно критично. Расход памяти от этого тоже не думаю что сильно увеличивался бы.
Вот пример из реального проекта
а почему *.jsx? Что "х" значит?
@affka jsx
— формат js включающий поддержку синтаксического сахара для React.js
По поводу require all
, не во всех проектах нужна вся мощь фреймворка, ОЧЕНЬ хотелось бы, чтобы фреймворк подгружал только то, что нужно
Example of jsx:
import React, { Component } from 'react';
export default class User extends Component {
render() {
return (
<div class="User">{this.props.username}</div>
);
}
}
Возьмем к примеру, у меня есть проект на express, при старте он занимает около 100Мб в ОЗУ. Если не заходить в админку, и пользоваться только клиент-сайд, то займет памяти не больше 200Мб. НО если полезть в админку, то всё станет интереснее, занимаемая приложением память увеличится до 500Мб.
Так о чём я, если я запускаю уже настроенный проект, я не хочу чтобы он сам по себе загружал ВСЁ! Хочется чтобы только то, что нужно. иначе ужс был б. Если бы не освобождение памяти по требованию, то приложение уже перевалило бы за 1ГБ ОЗУ, а мне нельзя, на вдс и так не много памяти
что-то сильно большие расходы памяти у вас для express, но в любом случае согласен, что фреймворк не должен все разом подключать. Учту это, когда буду переписывать под ES6
@affka Просто у меня в приложении ОЧЕНЬ много моделей и мало контроллеров/роутов. Пользователю дано редактировать почти всё что он видит.
что-то не видно поддержки импортов в node.js - https://nodejs.org/en/docs/es6/ в io.js этого тоже получается небыло?
@affka импорты будут не скоро. Но если фреймворк не поддерживает качественные импорты в ES6 это существенный минус.
Когда я говорил про es6 я имел ввиду нативное создание классов по месту
когда class Foo {}
идентично (function(){ function Foo(){}})()
.
В данный момент в Jii нельзя создать просто класс через Jii.createClass
он определяется где-то, но не здесь
Задачка для тех, кто хотел es6 - https://toster.ru/q/276621
@affka ответ: не нужно смешивать разные подходы
Jii перешел на es6 классы и поддержку es6. Тема более не актуальна
Есть несколько предложений по улучшению фреймворка для совместимости с ES6:
импорты: лучше расположить base.controller и base.model не в общем пакете, а например во вложенности. классы: посмотрите как реализует классы сейчас babel
как я бы хотел:
LestaD/Jii-Boilerplate-Basic-NextGenJS Сейчас лучше развивать фреймворк в сторону js, так как node.js имеет отличную архитектуру от php, соответственно фреймворк должен иметь свою структуру