ãã®èšäºã¯ãWebixãElectronãããã³Node.jsã䜿çšããŠã¯ãã¹ãã©ãããã©ãŒã ã®ãã¹ã¯ãããã¢ããªã±ãŒã·ã§ã³ãäœæããç§ã®çµéšã段éçã«èª¬æããŠããŸãã
ããæ¥ãç§ãããç¥ã£ãŠããWebãã¯ãããžãŒã®ã¹ã¿ãã¯ã«åºã¥ããŠãã¹ã¯ãããã¢ããªã±ãŒã·ã§ã³ãäœæããããšæããŸããã ãã¹ã¯ãããããã°ã©ãã¯éåžžC ++ãJavaãCïŒã䜿çšãããããã®ç®çã®ããã«Webãã¯ãããžãŒã¹ã¿ãã¯ã軜lookããŠããããšãç¥ã£ãŠããŸãã ããããç§ã¯èªåã§ã¢ããªã±ãŒã·ã§ã³ãæžããã®ã§ã䜿ãæ £ããããŒã«ã䜿çšããããšã§ããã»ã¹ãé«éåã§ãããšå€æããŸããã ãããŠãã¡ããããããªããºããè¶ããŠãäœãèµ·ããããèŠããã£ãã ã€ãŸããçµæã¯éåžžã®Webã¢ããªã±ãŒã·ã§ã³ãšããŠããã¹ã¯ããããšããŠãèµ·åã§ããŸãã
å®æããã¢ããªã±ãŒã·ã§ã³ã®ã³ãŒãã¯GitHubããããŠã³ããŒãã§ããŸã ã
ã¢ããªã±ãŒã·ã§ã³ãè¡ãããš...ããã¯ãã€ãã³ããè¿œå ãç·šéãããã³åé€ã§ããTODOãªã¹ãã§ãïŒããã§ãªããã°...ïŒã ã€ãã³ãã«ã¯ãã¿ã€ãã«ãã³ã³ãã³ããäŒå Žãæ¥ä»ãåªå 床ããããŸãã ã€ã³ã¿ãŒãã§ã€ã¹ããã·ã¢èªãšè±èªã«ç¿»èš³ããæ©èœãå©çšå¯èœã«ãªããŸãã ããããããŒã¿ãã¹ã¿ãŒããšåŒã³ãŸãããã
Webixã䜿çšããŠWebã¢ããªã±ãŒã·ã§ã³ãäœæããŸããã ããã¯ãã³ã³ããŒãã³ãã䜿çšããŠJavaScriptã·ã³ã¿ãã¯ã¹ã䜿çšããŠã¢ããªã±ãŒã·ã§ã³ãè¿ éã«æ§ç¯ããã¯ãã¹ãã©ãããã©ãŒã ããã³ã¯ãã¹ãã©ãŠã¶UIã©ã€ãã©ãªã§ãã Electronã䜿çšããŠãWebã¢ããªã±ãŒã·ã§ã³ããã¹ã¯ãããã«ã³ã³ãã€ã«ããŸããã ããã¯Node.jsã«åºã¥ãã¯ãã¹ãã©ãããã©ãŒã ããŒã«ã§ãããWebã¢ããªã±ãŒã·ã§ã³ãã³ã³ãã€ã«ããŠãç°ãªã容éã®ããŸããŸãªãã©ãããã©ãŒã ïŒWindowsãLinuxãMacïŒã§å®è¡ã§ããŸãã è£å©çãªããšã«ã¯ãNode.jsã«åºã¥ãããŒã«ã䜿çšãããŸãã
ãã©ã«ããŒæ§é ããå§ããŸãããã ãããžã§ã¯ãã®ã«ãŒãã§ã次ã®åœ¢åŒã§äœæããŸããã
- css-ã¹ã¿ã€ã«
- ããŒã¿-ããã¯ãšã³ã
- img-ç»å
- js-JavaScriptã¹ã¯ãªãã
Node.jsã¢ãžã¥ãŒã«ã®ã€ã³ã¹ããŒã«åŸããnode_modulesããã©ã«ããŒãè¿œå ããããcodebaseããã©ã«ããŒãWebixã«äœ¿çšãããããŸããŸãªãã©ãããã©ãŒã ã®ãã¹ã¯ãããã¢ããªã±ãŒã·ã§ã³ããŒãžã§ã³ããã/ release / DataMasterããã©ã«ããŒã«è¿œå ãããŸãã
ãã®çµæããããžã§ã¯ãã®æ§é ã¯æ¬¡ã®ããã«ãªããŸããã
ãããžã§ã¯ãã®ã«ãŒããã©ã«ããŒã¯ãµãŒããŒäžã«ããå¿ èŠããããŸãã ç§ã®å Žåãããã¯Apacheã§ãã
ããã§ã ãŸãã¯WebixããŠã³ããŒãããŒãžã«ã¢ã¯ã»ã¹ããŠããDownload Webix Standardããã¯ãªãã¯ããŸããã ããã¯ã©ã€ãã©ãªã®ç¡æããŒãžã§ã³ïŒã©ã€ã»ã³ã¹ãGNU GPLV3ãïŒã§ãããç§ãã¡ã®ããŒãºã«éåžžã«é©ããŠããŸãã Webix PROã®åçšçããããŸããããã¯ãäž»ã«ãŠã£ãžã§ããã®æ¡åŒµã©ã€ãã©ãªãšæè¡ãµããŒãæ©èœã«ãã£ãŠåºå¥ãããŸãã çµæã®webix.zipã¢ãŒã«ã€ããããã³ãŒãããŒã¹ãã©ã«ããŒããããžã§ã¯ãã®ã«ãŒãã«ã³ããŒããŸãã codebaseãã©ã«ããŒå ã§ãwebix.jsããã³webix.cssãã¡ã€ã«ã«æ³šæãæã£ãŠãã ããã ã¢ããªã±ãŒã·ã§ã³ã§ãããã®ãã¡ã€ã«ãæ¥ç¶ãããšãWebixã§äœæ¥ã§ããŸãã skinsãã©ã«ããŒã«ã¯ãããŒããå«ãcssãã¡ã€ã«ãå«ãŸããŠããŸãã
ãããžã§ã¯ãã«ãŒãã«index.htmlãã¡ã€ã«ãäœæããŸãã
index.html
<!DOCTYPE HTML> <html> <head> <link rel="stylesheet" href="codebase/skins/contrast.css" type="text/css"> <link rel="stylesheet" href="css/main.css" type="text/css"> <script src="codebase/webix.js" type="text/javascript"></script> <script src="codebase/i18n/en.js" type="text/javascript"></script> <script src="codebase/i18n/ru.js" type="text/javascript"></script> </head> <body> <script src="bundle.js" type="text/javascript"></script> </body> </html>
webix.jsãè¿œå ããŸãã webix.cssãæ¥ç¶ãããšãæšæºã®ããŒãã䜿çšããæ©äŒãäžããããŸãã ç§ã¯ããcodebase / skins / contrast.cssãã«ããçŽ æµã§æãå°ããªãããã¯ãæ¥ç¶ããããšã«ããŸããã ãŸããçµã¿èŸŒã¿ã®WebixããŒã«ãªãŒãŒã·ã§ã³æ©èœã䜿çšããããã«ããcodebase / i18nããã©ã«ããŒã®ãã¡ã€ã«ãå«ããŸããã ã€ã³ããã¯ã¹ãã¡ã€ã«ã«ã¯ããbundle.jsããã¡ã€ã«ãå«ããŸãã ãã¹ãŠã®jsã³ãŒãã®ã¢ã»ã³ããªããããŸãã ã¢ã»ã³ããªã«ã¯ãNode.jsãšGulpãå¿ èŠã§ãã
Node.jsããŸã ã€ã³ã¹ããŒã«ããŠããªãå Žåã¯ãããããå®è¡ã§ããŸã ã Node.jsãšãã©ãããã©ãŒã ããã±ãŒãžãããŒãžã£ãŒNPMã®ã€ã³ã¹ããŒã«ã確èªããã«ã¯ã
$ node -v
ããã³
$ npm -v
ã³ãã³ãã䜿çšããŸãã
ãjsããã©ã«ããŒã«ãã¢ããªã±ãŒã·ã§ã³ã®ã¡ã€ã³ããžãã¯ãäœæããŸãã internalization.jsãã¡ã€ã«ã«ã¯ãã¢ããªã±ãŒã·ã§ã³ã€ã³ã¿ãŒãã§ã€ã¹ãåœéåããããã®ãªããžã§ã¯ããå«ãŸããŠããŸãã æ¢åã®èšèªïŒãã·ã¢èªãè±èªïŒãšåæ§ã«ãå¿ èŠã«å¿ããŠä»ã®èšèªãè¿œå ã§ããŸãã
internalization.js
var translations = { // English "en-US": { localeName: "en-US", headerTitle: "Data master", resetFilters: "Reset filters", changeLocale: "Change language:", loadData: "Load data", addRow: "Add row", clearSelection: "Clear selection", deleteRow: "Delete row", saveData: "Save data", title: "Title", noItemSelected: "No item selected", dataSaved: "Data saved", reservedButton: "Reserved botton" }, // Russian "ru-RU": { localeName: "ru-RU", headerTitle: " ", resetFilters: " ", changeLocale: " :", loadData: " ", addRow: " ", clearSelection: " ", deleteRow: " ", saveData: "", title: "", noItemSelected: " ", dataSaved: " ", reservedButton: "..." } };
logic.jsãã¡ã€ã«ã«ã¯ãååãšã³ãŒãã®ã³ã¡ã³ãããç®çãç解ã§ããé¢æ°ãå«ãŸããŠããŸãã
logic.js
var defaultLocale = "en-US"; // object from translations.js var localizator = translations[defaultLocale]; /** * Get data from backend and fill datatable grid */ function getData() { $$("dataFromBackend").clearAll(); $$("dataFromBackend").load("http://localhost/data_master/data/data.php"); } /** * Add new row to datatable */ function addRow() { $$("dataFromBackend").add( { title: "-----", content: "-----", place: "-----" //date: "-----", //priority: "-----" } ); } /** * Reset selection in datatable grid */ function clearSelection() { $$("dataFromBackend").unselectAll(); } /** * Delete selected row */ function deleteRow() { if (!$$("dataFromBackend").getSelectedId()) { webix.alert(localizator.noItemSelected); return; } //removes the selected item $$("dataFromBackend").remove($$("dataFromBackend").getSelectedId()); } /** * Save data to backend from datatable grid */ function saveData() { var grid = $$("dataFromBackend"); var serializedData = grid.serialize(); webix.ajax().post("http://localhost/data_master/data/save.php", {data: serializedData}); webix.alert(localizator.dataSaved); } /** * Reset filters settings */ function resetFilters() { $$("dataFromBackend").getFilter("title").value = null; $$("dataFromBackend").getFilter("content").value = null; $$("dataFromBackend").getFilter("place").value = null; $$("dataFromBackend").getFilter("date").value = null; $$("dataFromBackend").getFilter("priority").value = null; // reload grid $$("dataFromBackend").clearAll(); $$("dataFromBackend").load("http://localhost/data_master/data/data.php"); } /** * Change translation to selected */ function changeLocale(locale) { localizator = translations[locale]; $$("headerContainer").define("template", localizator.headerTitle); $$("headerContainer").refresh(); $$("resetFiltersContainer").define("value", localizator.resetFilters); $$("resetFiltersContainer").refresh(); $$("changeLocale").define("label", localizator.changeLocale); $$("changeLocale").refresh(); $$("loadData").define("value", localizator.loadData); $$("loadData").refresh(); $$("addRow").define("value", localizator.addRow); $$("addRow").refresh(); $$("clearSelection").define("value", localizator.clearSelection); $$("clearSelection").refresh(); $$("deleteRow").define("value", localizator.deleteRow); $$("deleteRow").refresh(); $$("saveData").define("value", localizator.saveData); $$("saveData").refresh(); $$("reservedButton").define("value", localizator.reservedButton); $$("reservedButton").refresh(); webix.i18n.setLocale(locale); } /** * Function for reserved button */ function reservedButton() { // your code... }
ã»ãšãã©ã®é¢æ°ã¯ãonclickãã¿ã³ã®ã€ãã³ããã³ãã©ãŒã§ãã é¢æ°ã³ãŒãã¯ãåºæ¬çã«WebixèŠçŽ ãæäœããæ¹æ³ã§ãã äžè¬ã«ããã詳现ãªæ å ±ãå¿ èŠãªå Žåã¯ã Webixã®ããã¥ã¡ã³ãããŒãžãžãããããçŽæçã§ã ã
æšæºã®Webixã³ã³ããŒãã³ãã®ã©ãããŒã§ããobjects.jsãã¡ã€ã«ã«ã³ã³ã¹ãã©ã¯ã¿ãŒé¢æ°ãæ ŒçŽããããšãèšç»ããŠããŸããã ã¢ããªã±ãŒã·ã§ã³ã§é »ç¹ã«äœ¿çšããããŠã£ãžã§ãããé 眮ããããšãèããŸãããããã¿ã³èŠçŽ ã¯1ã€ã ã-æãç¹°ãè¿ããã-ã«éå®ããŸããã 以äžã«ãã®äœ¿çšæ³ã説æããŸãã
objects.js
/** * Create object with type "Button" * * @constructor */ function Button(id, value, type, width, onClickFunction) { this.view = "button"; this.id = id; this.value = value; this.type = type; this.width = width; this.on = { "onItemClick": function(){ onClickFunction(); } } }
æ§é ã¯ãstructure.jsãã¡ã€ã«ã§æå®ãããŸã
/** * Create main layout */ webix.ui({ view: "layout", id: "page", rows:[ { cols: [ { view:"icon", id: "headerIconContainer", icon:"calendar" }, { view:"template", id: "headerContainer", type:"header", template:"Data master" }, new Button("resetFiltersContainer", "Reset filters", "form", 150, resetFilters), { id: "divider", width: 20 }, { view: "combo", id: "changeLocale", label: 'Change locale:', labelWidth: 130, width: 230, align: "right", value: "en-US", options: [ "ru-RU", "en-US" ], on: { "onChange": function(newv, oldv) { changeLocale(newv); } } } ] }, { view: "datatable", id: "dataFromBackend", columns: [ { id: "title", header: [ { text: "<b>Title</b>" }, { content: "textFilter" } ], editor: "text", fillspace: 2 }, { id: "content", header: [ { text: "<b>Content</b>" }, { content: "textFilter" } ], editor: "popup", fillspace: 8 }, { id: "place", header: [ { text: "<b>Place</b>" }, { content: "textFilter" } ], editor: "text", fillspace: 2 }, { id: "date", header: [ "<b>Date</b>", { content: "dateFilter" } ], editor: "date", map: "(date)#date#", format: webix.Date.dateToStr("%d.%m.%Y"), fillspace: 2 }, { id: "priority", header: [ "<b>Priority</b>", { content: "selectFilter" } ], editor: "select", options: [1, 2, 3, 4, 5], fillspace: 1 } ], editable: true, select: "row", multiselect: true, // initial data load data: webix.ajax().post("http://localhost/electron_with_backend/data/data.php") }, { view: "layout", id: "buttonContainer", height: 50, cols: [ // Webix ui.button structure example: /*{ view: "button", id: "loadData", value: "Load data", type: "form", width: 150, on: { "onItemClick": function(id, e, trg){ getData(); } } },*/ new Button("loadData", "Load data", "form", 150, getData), new Button("addRow", "Add row", "form", 150, addRow), new Button("clearSelection", "Clear selection", "form", 150, clearSelection), new Button("deleteRow", "Delete row", "form", 150, deleteRow), new Button("saveData", "Save data", "form", 150, saveData), new Button("reservedButton", "Reserved button", "form", 150, reservedButton), {} ] } ] }); $$("buttonContainer").define("css", "buttonContainerClass"); $$("resetFiltersContainer").define("css", "resetFiltersContainerClass"); $$("headerIconContainer").define("css", "headerIconContainerClass"); $$("headerContainer").define("css", "headerContainerClass"); $$("changeLocale").define("css", "changeLocaleClass"); $$("divider").define("css", "dividerClass");
ä»çµã¿...è€æ°ã¬ãã«ã®æ§é ãæã€ãªããžã§ã¯ããwebix.uiïŒïŒã¡ãœããã«æž¡ãããŸãã ãã¥ãŒããããã£ã¯ãWebixãŠã£ãžã§ããã®ã¿ã€ãã決å®ããŸãããã®äŸã§ã¯ããã¬ã€ã¢ãŠããã§ãã ãããã®åã¯å€æ°ãããããããã«ç¬èªã®ã¡ãœãããšããããã£ããããŸãã ããã«ãwebix.protoUIïŒïŒã¡ãœããã䜿çšããŠæšæºã®Webixã³ã³ããŒãã³ããæ¡åŒµããå¿ èŠãªæ©èœãè¿œå ãŸãã¯ãªãŒããŒã©ã€ãã§ããŸãã ã芧ã®ãšãããWebixã®æäœã¯Javascriptã䜿çšããŠè¡ãããŠããããããã®ã©ã€ãã©ãªãæäœããããã®ãã¹ãŠã®ã³ãŒãã<script>ã¿ã°ã«å ¥ããŠããŸãã webix.uiïŒïŒã¡ãœããã§ã¯ãè¡ãšåã®ã·ãŒã±ã³ã¹ãæå®ããŸããããã®äžéšã¯ãå ¥ãåã«ãªã£ãè¡ãšåãæã¡ãã°ãªããã圢æããŸãããã®èŠçŽ ã¯ãããšãã°ãwidthãããã³ãheightãããããã£ã䜿çšããŠèšå®ã§ããŸãã èŠçŽ ãåãšè¡ã§ãå²ã¿ãã調æŽããŸãã ããšãã°ãããã§ãã¿ã³ãå®çŸ©ã§ããŸãã
{ view: "button", id: "loadData", value: "Load data", type: "form", width: 150, on: { "onItemClick": function(id, e, trg){ getData(); } }
idããããã£ã¯ãWebixããããã£ã®view_idã§ããã$$ïŒïŒã¡ãœããã䜿çšããŠèŠçŽ ã«ã¢ã¯ã»ã¹ã§ããŸãã ããšãã°ã$$ïŒ "loadData"ïŒã¯ãäžèšã®ã³ãŒãã§èª¬æãããã¿ã³ã®ãªããžã§ã¯ããè¿ããŸãã ãå€ãããããã£ã¯ããã¿ã³ã®ã©ãã«ããã¿ã€ãã-ã¿ã€ãããå¹ ã-å¹ ã決å®ããŸãã onãªããžã§ã¯ãã§ã¯ãèŠçŽ ã®ã€ãã³ããã³ãã©ãŒãå®çŸ©ã§ããŸãã äžèšã®äŸã§ã¯ãåäžïŒãonItemClickãïŒã§ãããgetDataïŒïŒé¢æ°ãåŒã³åºããonclickãã€ãã³ãã«å¯Ÿå¿ããŠããŸãã
äžèšã®æ§é ã®ä»£ããã«ããã¿ã³èŠçŽ ïŒãobjects.jsããã¡ã€ã«å ïŒã䜿çšããããã«ãã³ã³ã¹ãã©ã¯ã¿ãŒé¢æ°ã䜿çšããŸããã æž¡ããããã©ã¡ãŒã¿ãŒã«åŸã£ãŠButtonãªããžã§ã¯ããäœæããŠè¿ããŸãã ããã«ãããã³ãŒãã®éè€ãæé€ãã次ã®æ¹æ³ã§ãªããžã§ã¯ããäœæã§ããŸãã
new Button("loadData", "Load data", "form", 150, getData)
ã¡ãªã¿ã«ãã³ã³ãã€ã«æžã¿ã¢ããªã±ãŒã·ã§ã³ã§æé«ã®UXçšã®äºçŽãã¿ã³ãè¿œå ããŸããã ç§ã¯ãã®ããã®æ©èœãæãã€ããŸããã§ããã®ã§ãããªãã¯å¥œããªããã«ããã䜿ãããšãã§ããŸãã
components.jsãã¡ã€ã«ã®äžéšã«ã次ã®åœ¢åŒã®ã³ãŒãããããŸãã
$$("buttonContainer").define("css", "buttonContainerClass")
ãã®ããã«ããŠãèŠçŽ ã®ããããã£ãå®çŸ©ããã³å€æŽã§ããŸãïŒäŸã§ã¯ããbuttonContainerClassããšããå€ãæã€ã¯ã©ã¹å±æ§ãè¿œå ããŸãïŒã ããã§èª¬æããæ¹æ³ã¯ãããããããããããã«ç€ºããŠããŸãã ãcssãããããã£ã«å€ãå²ãåœãŠãããšã«ããããªããžã§ã¯ããã¯ã©ã¹ã§åæåã§ããŸãã
Webixã«ã¯ãããŒã¿ãã¢ããªã±ãŒã·ã§ã³ãšåã ã®èŠçŽ ã«ããŒãããããŸããŸãªæ¹æ³ããããŸãã getDataïŒïŒé¢æ°ã§ã¯ãloadïŒïŒã¡ãœããã䜿çšããŠããŒã¿ãã°ãªããã«ããŒãããŸããã ãã®ã¡ãœããã¯ãURLãdata / data.phpãã«ãã£ãŠããã¯ãšã³ãããåé€ãããŸãã
ã¢ããªã±ãŒã·ã§ã³ã®ããã¯ãšã³ãã¯ããšãŠã€ããªãã·ã³ãã«ã§ãã ãã®ãããªå°ããªã¢ããªã±ãŒã·ã§ã³ã«ã¯ããŒã¿ããŒã¹ã䜿çšããªãããšã«ããŸããã ããŒã¿ã¯data.jsonãã¡ã€ã«ã«ä¿åãããdata.phpã䜿çšããŠããããèªã¿åãããsave.phpã䜿çšããŠããã«ä¿åãããŸãã
data.php
<?php $dataFromFile = json_decode(file_get_contents("data.json")); echo json_encode($dataFromFile); /*$example_json_data = array( array (title => "My Fair Lady", year => 1964, votes => 533848, rating => 8.9, rank => 5), array (title => "Film 1", year => 1984, votes => 933848, rating => 6.9, rank => 4), array (title => "Film 2", year => 1966, votes => 53848, rating => 4.3, rank => 5), array (title => "Film 3", year => 1975, votes => 567848, rating => 2.9, rank => 2), array (title => "Film 4", year => 1981, votes => 433788, rating => 6.3, rank => 1) );*/ //echo json_encode($example_json_data);
save.php
<?php $data = $_POST["data"]; file_put_contents("data.json", $data);
ãã¡ãããåçšãããžã§ã¯ãã§ã¯ãããŸããŸãªããŒã¿ã®ãã§ãã¯ãšãšã©ãŒåŠçãè¡ãå¿ èŠããããŸãããããããããããããã«çç¥ããŸããã data-example.jsonãã¡ã€ã«ã«ãããã¥ã¡ã³ããµã€ãããååŸãããdatatableãèŠçŽ ãWebixã«ã¢ããããŒãããããã®ãµã³ãã«ããŒã¿æ§é ãé 眮ããŸããã
data-example.json
[ {"title":"My Fair Lady", "year":1964, "votes":533848, "rating":8.9, "rank":5}, {"title":"Film 1", "year":1984, "votes":933848, "rating":6.9, "rank":4}, {"title":"Film 2", "year":1966, "votes":53848, "rating":4.3, "rank":5}, {"title":"Film 3", "year":1975, "votes":567848, "rating":2.9, "rank":2}, {"title":"Film 4", "year":1981, "votes":433788, "rating":6.3, "rank":1} ]
ããŒã¿ã¯ãAJAXã¡ãœããwebix.ajaxïŒïŒãPostïŒïŒã䜿çšããŠsaveDataïŒïŒé¢æ°ã«ä¿åãããããã¯ãšã³ãã®URLãšããŒã¿ãªããžã§ã¯ããåãåããŸãã äžè¬ã«ãWebixã¯ããŸããŸãªæ¹æ³ã§ããŒã¿ãæäœã§ããŸããããšãã°ãjsonãxmlãªã©ãåãå ¥ããŠè¿ããŸãã ã¡ãªã¿ã«ãããŠã³ããŒããããWebixããŒãžã§ã³ã®ã¢ãŒã«ã€ãã«ã¯ãã³ãŒãããŒã¹ãã©ã«ããŒã«å ããŠãã·ã¹ãã ã®ããŸããŸãªã³ã³ããŒãã³ãã®æäœäŸãèŠãããšãã§ãããµã³ãã«ãã©ã«ããŒããããŸãã ãsamples / common / connectorããã©ã«ãã«ã¯ãããã¯ãšã³ããæäœããããã®ããã€ãã£ããããŒã¹ããããŸãã
ãããã£ãŠãäžè¬çã«ã¯ãã¢ããªã±ãŒã·ã§ã³ã®äœæ¥ã¯æ¬¡ã®ããã«å®è¡ãããŸã...èŠçŽ ãé 眮ãããè¡ãšåã§ã°ãªãããäœæãããŸãã èŠçŽ ãšå¯Ÿè©±ãããšãã€ãã³ããçºçãããããã®ã€ãã³ãã«å¯ŸããŠå®çŸ©ããããã³ãã©ãŒãå®è¡ãããŸãã äžéšã®ãã³ãã©ãŒã¯ã¡ãœããã䜿çšããŠããã¯ãšã³ããšéä¿¡ããããŒã¿ãåä¿¡ããã³ä¿åããŸãã åèšã§ãããŒã¿ã®åä¿¡ãšåŠçã«ããŒãžã®ãªããŒããäžèŠãªSPAã¢ããªã±ãŒã·ã§ã³ããããŸãã ã¢ããªã±ãŒã·ã§ã³ã€ã³ã¿ãŒãã§ã€ã¹ã®ç¿»èš³ã¯ãéžæãããã±ãŒã«ã«åŸã£ãŠç¿»èš³ãªããžã§ã¯ãã®ããããã£ãååŸããèŠçŽ ã®ãå€ãããããã£ã«æ°ããå€ãèšå®ãããããã®èŠçŽ ãæŽæ°ããããšã«ãã£ãŠå®è¡ãããŸãã ããžãã¯ã¯ãã³ã³ãããã¯ã¹ã®ãonChangeãã€ãã³ãã§ãã³ã°ããé¢æ°changeLocaleïŒïŒãåŒã³åºããŸãã ãšããã§ããã®é¢æ°ã«ã¯ãçµã¿èŸŒã¿ã¡ãœããwebix.i18n.setLocaleïŒãã±ãŒã«ïŒããããã³ã³ãããã¯ã¹ãããã±ãŒã«ãæž¡ããŸãã 詳现ã¯ãã¡ããã芧ãã ãã ã
次ã«ããã³ãã«å ã®ãã¹ãŠã®jsã³ãŒããåéããå¿ èŠããããŸãã ããããæåã«ãå°ãæºåäœæ¥ãããŠãã ããã ãããžã§ã¯ãã«ãŒãã®ã¡ã€ã³ã¢ããªã±ãŒã·ã§ã³èšå®ã§package.jsonãã¡ã€ã«ãäœæããŸãã
package.json
{ "name": "data_master", "description": "Simple ToDo list with desktop building", "version": "0.0.1", "homepage": "https://github.com/paratagas/data_master", "repository": { "type": "git", "url": "git+https://github.com/paratagas/data_master.git" }, "author": { "name": "Yauheni Svirydzenka", "email": "partagas@mail.ru", "url": "https://github.com/paratagas" }, "tags": [ "node.js", "webix", "electron", "ToDo list" ], "main": "main.js", "scripts": { "start": "electron .", "package": "electron-packager ./ DataMaster --all --out ~/release/DataMaster --overwrite" }, "dependencies": { "electron-prebuilt": "^0.35.6", "electron-packager": "^8.4.0" }, "devDependencies": { "gulp": "^3.9.0", "gulp-concat": "^2.6.0", "gulp-uglify": "^1.2.0", "gulp-sourcemaps": "^1.5.2" }, "license": "GPL-3.0" }
次ã«ãã³ãã³ã
$ npm install
ãå®è¡ããŠãå¿ èŠãªã³ã³ããŒãã³ããããŠã³ããŒãããŸãã ãããžã§ã¯ãã®ã«ãŒãã«ããgulpfile.jsãã¡ã€ã«ã§ãã¢ã»ã³ããªã®èšå®ãèšå®ããŸãã
gulpfile.js
var gulp = require('gulp'), uglify = require('gulp-uglify'), concat = require('gulp-concat'); // to create source mapping sourcemaps = require('gulp-sourcemaps'); /* * Collect all js files to one bundle script * Command: "gulp bundle" */ gulp.task('bundle', function() { // choose any files in directories and it's subfolders return gulp.src('js/**/*.js') .pipe(sourcemaps.init()) .pipe(concat('bundle.js')) .pipe(sourcemaps.write('./')) //.pipe(uglify()) // output result to current directory .pipe(gulp.dest('./')); }); /* * Watch js files changing and run task * Command: "gulp watch" */ gulp.task('watch', function () { gulp.watch('./js/**/*.js', ['bundle']); });
bindle.jsããã¹ãŠã®ã³ãŒãã§ã©ã®ããã«èŠãããã確èªã§ããããã«ãçž®å°ãã³ã¡ã³ãã¢ãŠãããŸããã ããã«ãCSSãããã¡ã€ã¯äœ¿çšããŸããã§ãããã¹ã¿ã€ã«ãå°æ°ã®ãã¡ã€ã«ã1ã€ãããªãããã§ãã å¿ èŠã«å¿ããŠããã®åäœãå€æŽã§ããŸãã ããã§ããããžã§ã¯ãã®ã«ãŒãã§
$ gulp bundle
å®è¡ããŠãããžã§ã¯ãããã«ãã§ããŸãã éçºäžã«ã
$ gulp watch
䜿çšãããšãjsãã¡ã€ã«ã®å€æŽã远跡ããããããã°ã
$ gulp bundle
å®è¡ã§ããŸãã
Webã¢ããªã±ãŒã·ã§ã³ã®æºåãæŽããéçšãµãŒããŒã§å®è¡ã§ããŸãã ç§ã¯æ¬¡ã®ãããªãã®ãåŸãŸããïŒ
ããã§ã¯ãElectronã䜿çšããŠãã¹ã¯ãããã«ããŸãã ããããææ°ããŒãžã§ã³ãéžæããŠããŠã³ããŒãã§ããŸãã åãªãªãŒã¹ããŒãžå ã«ã¯ãããŸããŸãªãã©ãããã©ãŒã ã®ããŒãžã§ã³ã®ãªã¹ãããããŸãã ãpackage.jsonãã¯ãäž»ãªäœæ¥ãè¡ããããã«ãã2ã€ã®ã¢ãžã¥ãŒã«ãå®çŸ©ããŸãã é»åäºåæ§ç¯ã¢ãžã¥ãŒã«ã¯ãã¢ããªã±ãŒã·ã§ã³ã®äºåçµã¿ç«ãŠãšèµ·åãæ åœããŸãã å¥éãã³ãã³ã
$ npm install --save-dev electron-prebuilt
ãŠã¢ãžã¥ãŒã«ãã€ã³ã¹ããŒã«ã§ããŸãã äžæ¹ãelectron-packagerã¢ãžã¥ãŒã«ã䜿çšãããšãã¿ãŒã²ãããã©ãããã©ãŒã ãŸãã¯ãã¹ãŠã®å¯èœãªãã©ãããã©ãŒã åãã«ã¢ããªã±ãŒã·ã§ã³ãã³ã³ãã€ã«ã§ããŸãã ã³ãã³ã
$ npm install --save-dev electron-packager
ã«ãã£ãŠåå¥ã«ã€ã³ã¹ããŒã«ãããŸãã
ã»ã¯ã·ã§ã³ã«æ³šæããŠãã ããïŒ
"scripts": { "start": "electron .", "package": "electron-packager ./ DataMaster --all --out ~/release/DataMaster --overwrite" },
å®çŸ©ãããã
$ npm start
ã³ãã³ãã䜿çšããŠã¢ããªã±ãŒã·ã§ã³ã®äºåã¢ã»ã³ããªã
$ npm start
ãã
$ npm run-script package
ã³ãã³ãã䜿çšããŠã³ã³ãã€ã«ã
$ npm start
$ npm run-script package
ã ã¡ãªã¿ã«ãããšãã°
"package": "electron-packager ./ DataMaster --win32-x64 --out ~/release/DataMaster --overwrite"
packageã³ãã³ããå€æŽãããšã
"package": "electron-packager ./ DataMaster --win32-x64 --out ~/release/DataMaster --overwrite"
ã«ãªããŸã
"package": "electron-packager ./ DataMaster --win32-x64 --out ~/release/DataMaster --overwrite"
å Žåãã¢ããªã±ãŒã·ã§ã³ã¯ã¿ãŒã²ãããã©ãããã©ãŒã çšã«ã³ã³ãã€ã«ãããŸãã Windows x64ã Electronã¯çŸåšãWindows x32 / x64ãLinux x32 / x64 / armv7ãOS X / x64ã®ãã©ãããã©ãŒã ããµããŒãããŠããŸãã ããå®å šã«ç解ããã«ã¯ã ããã¥ã¡ã³ããåç §ããŠãã ããã
ãããžã§ã¯ãã«ãŒãã«main.js.ãã¡ã€ã«ãäœæããŸã Electronã®èšå®ã«å¿ èŠã§ãã
main.js
/* * Commands: * npm init - initialize npm in current directory * npm install - install modules * npm install --save-dev electron-prebuilt - install module for pred-build * npm install --save-dev electron-packager - install module for build * npm start - to start app * npm run-script package - to compile app */ const electron = require('electron'); // lifecycle of our app const app = electron.app; // create window for our app const BrowserWindow = electron.BrowserWindow; // To send crash reports to Electron support // electron.crashReporter.start(); // set global link // if not, the window will be closed after garbage collection var mainWindow = null; /** * Check that all windows are closed before quiting app */ app.on('window-all-closed', function() { // OS X apps are active before "Cmd + Q" command. Close app if (process.platform != 'darwin') { app.quit(); } }); /** * Create main window menu */ function createMenu() { var Menu = electron.Menu; var menuTemplate = [ { label: 'File', submenu: [ { label: 'New window', click: function() { createSubWindow(); } }, {type: "separator"}, { label: 'Exit', click: function() { app.quit(); } } ] }, { label: 'Edit', submenu: [ { label: 'Cut', role: 'cut' }, { label: 'Copy', role: 'copy' }, { label: 'Paste', role: 'paste' } ] }, { label: 'About', submenu: [ { label: 'Name', click: function() { console.log(app.getName()); } }, { label: 'Version', click: function() { console.log(app.getVersion()); } }, { label: 'About', click: function() { console.log('ToDo list'); } } ] }, { label: 'Help', submenu: [ { label: 'Node.js docs', click: function() { require('electron').shell.openExternal("https://nodejs.org/api/"); } }, { label: 'Webix docs', click: function() { require('electron').shell.openExternal("http://docs.webix.com/"); } }, { label: 'Electron docs', click: function() { require('electron').shell.openExternal("http://electron.atom.io/docs/all"); } } ] } ]; var menuItems = Menu.buildFromTemplate(menuTemplate); Menu.setApplicationMenu(menuItems); } /** * Create main window */ function createMainWindow() { mainWindow = new BrowserWindow({ title: "Data master", resizable: false, width: 910, height: 800, // set path to icon for compiled app icon: 'resources/app/img/icon.png', // set path to icon for launched app //icon: 'img/icon.png' center: true // to open dev console: The first way //devTools: true }); createMenu(); // load entry point for desktop app mainWindow.loadURL('file://' + __dirname + '/index.html'); // to open dev console: The second way //mainWindow.webContents.openDevTools(); // Close all windows when main window is closed mainWindow.on('closed', function() { mainWindow = null; newWindow = null; }); } /** * Create sub menu window */ function createSubWindow() { newWindow = new BrowserWindow({ title: "Go to GitHub", resizable: false, // imitate mobile device width: 360, height: 640, icon: 'resources/app/img/mobile.png', center: true }); newWindow.loadURL("https://github.com/"); newWindow.on('closed', function() { newWindow = null; }); } /** * When Electron finish initialization and is ready to create browser window */ app.on('ready', function() { createMainWindow(); });
ãã¡ã€ã«å ã®ã³ã¡ã³ãã¯ãããã€ãã®ã¹ãããã®ç®çã説æããŠããŸãã äžè¬çã«ã¯ãelectronãªããžã§ã¯ããäœæããŠããã¢ããªã±ãŒã·ã§ã³ãŠã£ã³ããŠãäœæãããããæ§æããŸãã ãã®åŸã次ã®ããã«ãã¢ããªã±ãŒã·ã§ã³ã®ã¡ã€ã³URLããŠã£ã³ããŠã«éä¿¡ãããŸã
mainWindow.loadURL('file://' + __dirname + '/index.html')
ã ç§ãã¡ã®å Žåãããã¯ãããžã§ã¯ãã®ã«ãŒãã«ãããindex.htmlããã¡ã€ã«ã§ãã æåŸã«ãåŒ
mainWindow = null
ã«ãã£ãŠããŠã£ã³ããŠãžã®ãªã³ã¯
mainWindow = null
åé€ããŸããããã¯ãã¢ããªã±ãŒã·ã§ã³ãè€æ°ã®ãŠã£ã³ããŠããµããŒãããŠããå Žåã察å¿ããèŠçŽ ãåé€ããç¬éããã£ããããå¿ èŠãããããã§ãã ãã®å Žåãã¡ã€ã³ã¢ããªã±ãŒã·ã§ã³ãŠã£ã³ããŠãéãããšãåãŠã£ã³ããŠãéããããŸãïŒnullãèšå®ãããŸãïŒã èšå®ã§ã¯ãå®æãããã¹ã¯ãããã¢ããªã±ãŒã·ã§ã³ã®ã¢ã€ã³ã³ãèšå®ããããšãã§ããŸãã ãããè¡ãã«ã¯ã
icon: 'resources/app/img/icon.png'
æå®ã
icon: 'resources/app/img/icon.png'
ããã§ããresources / appãã¯ããœãŒã¹ã³ãŒããã¢ããªã±ãŒã·ã§ã³ã®ã³ã³ãã€ã«æžã¿ããŒãžã§ã³ã«ä¿åãããŠããå Žæã§ãã
Electronã§ã¯ãã¢ããªã±ãŒã·ã§ã³ãŠã£ã³ããŠã®ã«ã¹ã¿ã ã¡ãã¥ãŒãäœæããããšãã§ããŸãã ãã¢ã³ã¹ãã¬ãŒã·ã§ã³ã®ç®çã§ããããã©ã®ããã«è¡ããããã瀺ãããã«ããã€ãã®ã¡ãã¥ãŒé ç®ãè¿œå ããŸããã ãã®ãããã¯ã«é¢ããè¯ãæ å ±ã¯ã å ¬åŒããã¥ã¡ã³ãã«ãããŸã ã ã¡ãã¥ãŒé ç®
File > New window
]
File > New window
]ã§ãæ°ãããŠã£ã³ããŠãè¿œå ããŸããã ã¢ãã€ã«ããã€ã¹ã§ã³ã³ãã³ãã®è¡šç€ºãã·ãã¥ã¬ãŒãããGitHubããŒãžãéããŸãã Webã¢ããªã±ãŒã·ã§ã³ã§æ°ãããŠã£ã³ããŠã®éå§URLãèšå®ããŠãããšãã°æ©èœãåé¢ããå¿ èŠãããå Žåã«å¥ã®ãšã³ããªãã€ã³ããäœæã§ããŸãã
éçºã¢ãŒãã§ã¯ãChrome Dev Toolsãã¢ã¯ãã£ãåã§ããŸãã ãmain.jsããã¡ã€ã«ã®ã³ã¡ã³ãã¯ããããè¡ãããã®ããã€ãã®æ¹æ³ã瀺ããŠããŸãã
ã³ãã³ã
$ npm run-script package
ãå®è¡ãããšãããŸããŸãªãã©ãããã©ãŒã åãã®æ¢è£œã®ã¢ããªã±ãŒã·ã§ã³ããã/ release / DataMasterãã«è¡šç€ºãããŸãã
è¿œå ã®ãŠã£ã³ããŠãéããšããã¥ãŒã¯æ¬¡ã®ããã«ãªããŸãã
ãã®çµæã誰ãã«ãšã£ãŠäŸ¿å©ãªå®å šã«æ©èœããã¢ããªã±ãŒã·ã§ã³ãåŸãŸããã ãããžã§ã¯ãã³ãŒãã¯ãéçºã®ãã¹ããã©ã¯ãã£ã¹ã§ãããšã¯äž»åŒµããŠããŸãããïŒè©ŠããŠã¿ãŸãããïŒãããããã䜿çšããããã¯ãããžãšãããã®çžäºäœçšã¯èª°ãã«ãšã£ãŠèå³æ·±ããã®ã«ãªãã§ãããã å®éããã®ããã«ç§ã¯ãã®èšäºãæžããŸããã çµå±ããããã®ããŒã«ã«ã€ããŠäžåºŠåŠãã ã®ã¯Habrã®èšäºããã§ããããä»ã§ã¯åãã§äœ¿çšããŠããŸãã ãã®ã¢ããªã±ãŒã·ã§ã³ã§ã¯ãWebixãšElectronã®æ©èœã®ããäžéšãã䜿çšããŠããªãããšã«æ³šæããŠãã ããã å®éããããã®ããŒã«ã¯ããªãåºç¯ãªæ©èœãåããŠããããããã䜿çšããããšã§ã匷åºãªã¯ãã¹ãã©ãããã©ãŒã ã¢ããªã±ãŒã·ã§ã³ãäœæã§ããŸãã
å€æŽãšè¿œå
ã³ã¡ã³ãïŒ Justborisã«æè¬ïŒã§èšäºãšãããžã§ã¯ãã«ã€ããŠè°è«ããå人ãšäžç·ã«Node.jsãšExpressãããŒã¹ãšããŠã¢ããªã±ãŒã·ã§ã³ã®ããã¯ãšã³ããæžãçŽãããä¿ããŸããã
ããã«ãããApacheãšPHPãæŸæ£ãããããžã§ã¯ãã®äŸåé¢ä¿ãæžããããšãã§ããŸããã
ãã¡ã€ã«ãserver.jsãã¯ããã¹ãŠã®ãµãŒããŒããžãã¯ãèšè¿°ãããããžã§ã¯ãã®ã«ãŒãã«äœæãããŸããã
server.js
const express = require('express'); const bodyParser = require('body-parser'); const fs = require('fs'); var cors = require('cors'); var path = require("path"); const app = express(); const port = 3000; // use to parse json data app.use(bodyParser.json()); // use to create cross-domain requests (CORS) app.use(cors()); // create path aliases to use them in index.html file // otherwise the assets in it will not work and icons will not be shown // scheme: // app.use('/my_path_alias', express.static(path.join(__dirname, '/path_to_where/my_assets_are'))); app.use('/css', express.static(path.join(__dirname, '/css'))); app.use('/skins', express.static(path.join(__dirname, '/codebase/skins'))); app.use('/bundle', express.static(path.join(__dirname, '/'))); app.use('/codebase', express.static(path.join(__dirname, '/codebase'))); app.use('/i18n', express.static(path.join(__dirname, '/codebase/i18n'))); app.use('/fonts', express.static(path.join(__dirname, '/codebase/fonts'))); const filePath = __dirname + '/data/'; const fileName = "data.json"; /** * Get index page * * @param {string} URL * @param {function} Callback */ app.get('/', (req, res) => { res.sendFile(path.join(__dirname + '/index.html')); }); /** * Send GET request to get data * * @param {string} URL * @param {function} Callback */ app.get('/data', (req, res) => { const options = { root: filePath }; res.sendFile(fileName, options, function (err) { if (err) { console.log('Error:', err); } else { console.log('Received:', fileName); } }); }); /** * Send POST request to save data * * @param {string} URL * @param {function} Callback */ app.post('/data', (req, res) => { // use JSON.stringify() 2nd and 3rd param to create pretty JSON data // remove them for minified JSON fs.writeFile(filePath + fileName, JSON.stringify(req.body, null, 4), 'utf-8', (err) => { if (err) { console.log('Error:', err); } res.status(200).send(req.body); }); }); /** * Listen to server with specified port * * @param {string} Port * @param {function} Callback */ app.listen(port, () => { // open browser on http://localhost:3000 console.log('Server is running on http://localhost:' + port); });
ã³ãŒãã®ã³ã¡ã³ãã¯ãã®ç®çã説æããŠããŸããããã€ãã®ç¹ã«ã€ããŠã話ãããããšæããŸãã
ãŸããã¡ã€ã³ãµãŒããŒãaddress
http://localhost:3000
ã«é 眮ãããŠããããããã¡ã€ã«ãjs / logic.jsãããã³ãjs / structure.jsãã®ãã¹ãå€æŽããå¿ èŠããããŸããããããŠãããã§æåã®åé¡ã«ééããŸãããããã©ã«ãã§ãwebix.ajaxïŒïŒãPostïŒïŒã圢åŒã®Webixãªã¯ãšã¹ãã®HTTPããããŒãã©ã¡ãŒã¿ãContent-typeãã®å€ïŒãapplication / x-www-form-urlencodedããããã«ããããã¡ã€ã«ãdata / data.jsonãã«ä¿åããããŒã¿ãæ£ããåŠçã§ããŸããã§ããããapp.setïŒïŒãã䜿çšããŠExpressãµãŒããŒããããããŒãéä¿¡ããããšãã§ããŸããã§ãããããããŒããªã¯ãšã¹ãã«çŽæ¥æž¡ãããšã§æ±ºå®ããŸããã
webix.ajax().headers({ "Content-Type": "application/json" }).post("http://localhost:3000/data", {data: serializedData});
ãããã£ãŠãã¢ããªã±ãŒã·ã§ã³ã«ã¯3ã€ã®URLã衚瀺ãããŸããã
- localhostïŒ3000-ã¡ã€ã³ããŒãžãååŸããããã®GETãªã¯ãšã¹ã
- localhostïŒ3000 / data-ããŒã¿ãåä¿¡ããããã®AJAX GETãªã¯ãšã¹ã
- localhostïŒ3000 / data-ããŒã¿ãä¿åããããã®AJAX POSTãªã¯ãšã¹ã
2çªç®ã®åé¡ã¯ãã¯ãã¹ãã¡ã€ã³ãªã¯ãšã¹ãïŒCORSïŒã§ã®Javascriptã®çŠæ¢ãåå ã§çºçããŸãããããŸããŸãªããããŒã䜿çšããããšäœåºŠãè©Šã¿ãåŸãç§ã¯Node.jsã¢ãžã¥ãŒã«ã«é¢ããæ å ±ããããäžã§èŠã€ããŸãããããã¯corsãšåŒã°ããŠããŸãããã®çµæã2è¡ç®ã®ã³ãŒãã¯1è¡ã®ã³ãŒãã§è§£æ±ºãããŸããã
app.use(cors());
ã
ã€ã³ããã¯ã¹ããŒãžã®è¡šç€ºäžã«3çªç®ã®åé¡ãçºçããŸãããExpressã¯ãã¹ã¿ã€ã«ãšã¹ã¯ãªããããã®ãŸãŸã®åœ¢åŒã§è¡šç€ºããããšãæã¿ãŸããã§ãããããªãã¯æ¯èŒããããšãã§ããŸãïŒããªããäžã§èŠãããšãã§ããå€ããindex.htmlãïŒ...
æ°ããindex.html
<!DOCTYPE HTML> <html> <head> <link rel="stylesheet" href="skins/contrast.css" type="text/css"> <link rel="stylesheet" href="css/main.css" type="text/css"> <script src="codebase/webix.js" type="text/javascript"></script> <script src="i18n/en.js" type="text/javascript"></script> <script src="i18n/ru.js" type="text/javascript"></script> </head> <body> <script src="bundle/bundle.js" type="text/javascript"></script> </body> </html>
æ°ãããã¹ãæ©èœãããã«ã¯ããserver.jsãã«ãã¹ãšã€ãªã¢ã¹ãç»é²ããå¿ èŠããããŸããã
app.use('/css', express.static(path.join(__dirname, '/css'))); app.use('/skins', express.static(path.join(__dirname, '/codebase/skins'))); app.use('/bundle', express.static(path.join(__dirname, '/'))); app.use('/codebase', express.static(path.join(__dirname, '/codebase'))); app.use('/i18n', express.static(path.join(__dirname, '/codebase/i18n'))); app.use('/fonts', express.static(path.join(__dirname, '/codebase/fonts')));
ããã®app.useïŒïŒã®æåã®ãã©ã¡ãŒã¿ãŒã¯ãã¹ãšã€ãªã¢ã¹ã§ã2çªç®ã¯ãã¹èªäœã§ããããã§ãããšãã°ãindex.htmlãã§ããã¹ãskinsããåç §ããå¿ èŠããããŸãã
<link rel="stylesheet" href="skins/contrast.css" type="text/css">
代ããã«ïŒä»¥åã ã£ãïŒïŒ
<link rel="stylesheet" href="codebase/skins/contrast.css" type="text/css">
ãããã£ãŠããpackage.jsonãã®æ°ããã¢ãžã¥ãŒã«ã䜿çšããããã«ããexpressãããbody-parserããããã³ãcorsããšããæ°ããäŸåé¢ä¿ãç»é²ããŸããã
éçºã容æã«ããããã«ãNodemonããã±ãŒãžãã€ã³ã¹ããŒã«ããŸãããããã¯ããããžã§ã¯ããã¡ã€ã«ãžã®å€æŽãç£èŠããïŒããå ŽåïŒãµãŒããŒãåèµ·åããã¢ãžã¥ãŒã«ã§ãã
ã³ãã³ãã®ã³ã¬ã¯ã·ã§ã³ã«ç»å ŽããŸããïŒ
$ npm run nodemon
éçºã¢ãŒãã§
$ npm run server
ãµãŒããŒãèµ·åãããããšãäœæ¥ã¢ãŒãã§ãµãŒããŒãèµ·åããããã§ãã
ããã§ãæåŸã®ã³ãã³ãã¯ãWebããŒãžã§ã³ãšãã¹ã¯ãããã®äž¡æ¹ã®ã¢ããªã±ãŒã·ã§ã³ã®èµ·åã«å è¡ããã¯ãã§ãããŸãããµãŒããŒã¯ã³ã³ãã€ã«æã«åäœããã¯ãã§ãã
ããã§ãã¢ããªã±ãŒã·ã§ã³ã®äŸåé¢ä¿ãå°ãªããªããçµã¿èŸŒã¿ã®Node.jsãµãŒããŒã䜿çšãããŸãã
ãæ°ã¥ããããããŸããããserver.jsãã¡ã€ã«ã¯ïŒä»¥åã®jsã³ãŒãäŸãšã¯ç°ãªãïŒES6æšæºã®æ§æãèæ ®ããŠèšè¿°ãããŠããŸããå°æ¥çã«ã¯ãES6ã§ãããžã§ã¯ãå šäœãæžãçŽãäºå®ã§ãããããžã§ã¯ãã³ãŒãïŒä¿®æ£æžã¿ïŒã¯ãGitHubã§åŒãç¶ãå©çšã§ããŸãã