{"@attributes":{"version":"2.0"},"channel":{"title":"Radomir Sohlich","link":"https:\/\/sohlich.github.io\/tags\/javascript\/index.xml","description":"Recent content on Radomir Sohlich","generator":"Hugo -- gohugo.io","copyright":"\u00a9 2017 Radomir Sohlich","item":{"title":"Angular on Electron, part 1","link":"https:\/\/sohlich.github.io\/post\/angular_electron\/","pubDate":"Sat, 29 Jul 2017 08:48:41 +0200","guid":"https:\/\/sohlich.github.io\/post\/angular_electron\/","description":"\n\n<p>Today it is possible to have almost all the applications as a service online. Literally you don&rsquo;t have to install any of it on you computer. Even if this is possible, but for me it is still more comfortable to have a dedicated desktop application. I believe I&rsquo;m not the only one. There are a lot of ways how to create a desktop application. Utilizing the native frameworks like Qt, WxWidgets is always an option. For Java people, there are two useful options: swing and java fx.\nBut for me as web developer, though java based, it means to learn a new library or whole framework, all its features and pitfalls&hellip; But what If anybody tells you that you can use your good &ldquo;old&rdquo; javascript and HTML? Me, I\u2019m totally IN.<\/p>\n\n<p>So here comes the Electron platform (<a href=\"https:\/\/electron.atom.io\/\">https:\/\/electron.atom.io\/<\/a>) based on Chromium browser. It provides presentation layer and runtime for your application.\nThe Electron accompanied by Angular framework is a very solid foundation for desktop application development in most of use cases. By the way lot of well known applications are based on electron: VS Code, Slack, WhatsApp&hellip;<\/p>\n\n<p>I&rsquo;ll try to show you how to start your own project, or &ldquo;Electronify&rdquo; the existing one.<\/p>\n\n<h1 id=\"bootstrap-your-project\">Bootstrap your project<\/h1>\n\n<p>Using an Angular CLI generate a new application and test the first run. After following command you should be able to see the result in the browser on URL <a href=\"http:\/\/localhost:4200\">http:\/\/localhost:4200<\/a>.<\/p>\n\n<pre><code>&gt; ng new electron_app\n&gt; ng serve\n<\/code><\/pre>\n\n<p>Add main file for the electron called main.js<\/p>\n\n<p>${PROJECT_FOLDER}\/main.js:<\/p>\n\n<pre><code>    const { app, BrowserWindow } = require('electron');\n    \n    \/\/ Executes when the application \n    \/\/ is initialized.\n    app.on('ready', function() {\n        console.log('Starting application!');\n        \/\/ Create browser window \n        \/\/ with given parameters\n        mainWindow = new BrowserWindow({ width: 1280, height: 960 });\n        mainWindow.loadURL(&quot;http:\/\/localhost:4200&quot;);\n    \n        \/\/ It is useful to open dev tools\n        \/\/ for debug.\n        mainWindow.webContents.openDevTools();\n        mainWindow.on('closed', function() {\n            mainWindow = null;\n        });\n    });\n    \n    \/\/ Defines the behavior on close.\n    app.on('window-all-closed', function() {\n        app.quit();\n    });\n<\/code><\/pre>\n\n<p>And update the package.json file by few additional properties:\n${PROJECT_FOLDER}\/package.json:<\/p>\n\n<pre><code>    {\n        &quot;name&quot;: &quot;electron_app&quot;,\n        &quot;version&quot;: &quot;0.0.0&quot;,\n        &quot;main&quot;: &quot;main.js&quot;,\n        &quot;license&quot;: &quot;MIT&quot;,\n        &quot;scripts&quot;: {\n            &quot;ng&quot;: &quot;ng&quot;,\n            &quot;start&quot;: &quot;ng serve&quot;,\n            &quot;build&quot;: &quot;ng build&quot;,\n            &quot;test&quot;: &quot;ng test&quot;,\n            &quot;lint&quot;: &quot;ng lint&quot;,\n            &quot;e2e&quot;: &quot;ng e2e&quot;\n        },\n        &quot;private&quot;: true,\n        &quot;dependencies&quot;: {\n            &quot;@angular\/animations&quot;: &quot;^4.0.0&quot;,\n            &quot;@angular\/common&quot;: &quot;^4.0.0&quot;,\n            &quot;@angular\/compiler&quot;: &quot;^4.0.0&quot;,\n            &quot;@angular\/core&quot;: &quot;^4.0.0&quot;,\n            &quot;@angular\/forms&quot;: &quot;^4.0.0&quot;,\n            &quot;@angular\/http&quot;: &quot;^4.0.0&quot;,\n            &quot;@angular\/platform-browser&quot;: &quot;^4.0.0&quot;,\n            &quot;@angular\/platform-browser-dynamic&quot;: &quot;^4.0.0&quot;,\n            &quot;@angular\/router&quot;: &quot;^4.0.0&quot;,\n            &quot;core-js&quot;: &quot;^2.4.1&quot;,\n            &quot;rxjs&quot;: &quot;^5.4.1&quot;,\n            &quot;zone.js&quot;: &quot;^0.8.14&quot;\n        },\n        &quot;devDependencies&quot;: {\n            &quot;@angular\/cli&quot;: &quot;1.2.4&quot;,\n            &quot;@angular\/compiler-cli&quot;: &quot;^4.0.0&quot;,\n            &quot;@angular\/language-service&quot;: &quot;^4.0.0&quot;,\n            &quot;@types\/jasmine&quot;: &quot;~2.5.53&quot;,\n            &quot;@types\/jasminewd2&quot;: &quot;~2.0.2&quot;,\n            &quot;@types\/node&quot;: &quot;~6.0.60&quot;,\n            &quot;codelyzer&quot;: &quot;~3.0.1&quot;,\n            &quot;jasmine-core&quot;: &quot;~2.6.2&quot;,\n            &quot;jasmine-spec-reporter&quot;: &quot;~4.1.0&quot;,\n            &quot;karma&quot;: &quot;~1.7.0&quot;,\n            &quot;karma-chrome-launcher&quot;: &quot;~2.1.1&quot;,\n            &quot;karma-cli&quot;: &quot;~1.0.1&quot;,\n            &quot;karma-coverage-istanbul-reporter&quot;: &quot;^1.2.1&quot;,\n            &quot;karma-jasmine&quot;: &quot;~1.1.0&quot;,\n            &quot;karma-jasmine-html-reporter&quot;: &quot;^0.2.2&quot;,\n            &quot;protractor&quot;: &quot;~5.1.2&quot;,\n            &quot;ts-node&quot;: &quot;~3.0.4&quot;,\n            &quot;tslint&quot;: &quot;~5.3.2&quot;,\n            &quot;typescript&quot;: &quot;~2.3.3&quot;\n        }\n    }\n<\/code><\/pre>\n\n<p>I recommend to install the electron platform globaly with command:<\/p>\n\n<pre><code>    &gt; npm install -g electron\n<\/code><\/pre>\n\n<p>The first simple manual run could be done by calling following commands (these must be run in separate terminal windows as the \u201cng serve\u201d is blocking)<\/p>\n\n<pre><code>    &gt; ng serve\n    &gt; electron .\n<\/code><\/pre>\n\n<p>Command \u201cng serve\u201d will start development server on <a href=\"http:\/\/localhost:4200\">http:\/\/localhost:4200<\/a>, you can notice the this url is used in main.js file. The &ldquo;electron .&rdquo; will start the electron app by executing the main.js file.<\/p>\n\n<p>You can use <a href=\"https:\/\/www.npmjs.com\/package\/concurrently\">concurrently<\/a> tool to run these two commands concurrently. Also it can be incorporated to package.json file as an npm script.<\/p>\n\n<pre><code>npm install -g concurrently\n<\/code><\/pre>\n\n<p>${PROJECT_FOLDER}\/package.json<\/p>\n\n<pre><code>&quot;scripts&quot;: {\n        ...\n        &quot;electrondev&quot;: &quot;concurrently -k \\&quot;ng serve\\&quot; \\&quot;electron .\\&quot;&quot;\n    },\n<\/code><\/pre>\n\n<h1 id=\"serving-static-files\">Serving static files<\/h1>\n\n<p>Serving angular application via development server is not very comfortable and permanent solution. Better approach is serving a static files from the build output folder (let&rsquo;s call it distribution folder). The main.js file need to be changed to open the index.html file located in distribution folder of your angular application.<\/p>\n\n<p>${PROJECT_FOLDER}\/main.js<\/p>\n\n<pre><code>    const { app, BrowserWindow } = require('electron');\n    path = require('path');\n    url = require('url');\n    app.on('ready', function() {\n        console.log('Starting application!');\n        mainWindow = new BrowserWindow({ width: 1280, height: 960 });\n        \n        \/\/ Change loadUrl to load index.html\n        \/\/ using url and path package \n        \/\/ to format the file url\n        mainWindow.loadURL(url.format({\n            \/\/__dirname is the current working dir\n            pathname: path.join(__dirname, 'dist', 'index.html'),\n            protocol: 'file:',\n            slashes: true\n        }));\n    \n        \/\/ Opens dev tools\n        mainWindow.webContents.openDevTools();\n        mainWindow.on('closed', function() {\n            mainWindow = null;\n        });\n    });\n    app.on('window-all-closed', function() {\n        app.quit();\n    });\n<\/code><\/pre>\n\n<p>After you open electron you will receive \u201cFailed to load resource\u201d error.\nThere is one step missing to get the change work.\n<img src =\"https:\/\/d2mxuefqeaa7sj.cloudfront.net\/s_F68920300BC018EB3E1E88614B689BAD376E939D730AA4BF30888F46A4DF2F8A_1501387336733_image.png\"\/><\/p>\n\n<p>The one small change that need to be done is in your index.html file. We need to define the base for the file as absolute but from the actual working directory like \u201c.\/\u201d. This is done in <base> element in head tag of index.html . After the modification you can try \u201celectron .\u201d in your ${PROJECT_FOLDER}<\/p>\n\n<p>${PROJECT_FOLDER}\/index.html :<\/p>\n\n<pre><code>    &lt;!doctype html&gt;\n    &lt;html lang=&quot;en&quot;&gt;\n    &lt;head&gt;\n        &lt;meta charset=&quot;utf-8&quot;&gt;\n        &lt;title&gt;Electron&lt;\/title&gt;\n        &lt;!-- Change the href attribute \n        to reference to cur. working dir --&gt;\n        &lt;base href=&quot;.\/&quot;&gt;\n        &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1&quot;&gt;\n        &lt;link rel=&quot;icon&quot; type=&quot;image\/x-icon&quot; href=&quot;favicon.ico&quot;&gt;\n    &lt;\/head&gt;\n    &lt;body&gt;\n        &lt;app-root&gt;&lt;\/app-root&gt;\n    &lt;\/body&gt;\n    &lt;\/html&gt;\n<\/code><\/pre>\n\n<p>That&rsquo;s it. Desktop application with Angular. The same approach could be used with other JS frameworks or just pure static HTML. I was excited how easy it is.<\/p>\n\n<p>The repository with example project <a href=\"https:\/\/github.com\/sohlich\/angular_on_electron\">https:\/\/github.com\/sohlich\/angular_on_electron<\/a><\/p>\n\n<h3 id=\"series\">Series:<\/h3>\n\n<ul>\n<li><a href=\"https:\/\/sohlich.github.io\/post\/angular_electron\/\">Angular on Electron, part 1<\/a><\/li>\n<li><a href=\"https:\/\/sohlich.github.io\/post\/angular_electron_2\/\">Angular on Electron, part 2<\/a><\/li>\n<\/ul>\n"}}}