Jak jsem vytvořil svou první aplikaci Electron &You Can Too Pt.2 – Příprava pracovního postupu

Chcete si tedy vytvořit vlastní elektronovou aplikaci? Máte v hlavě nějaký zajímavý nápad, nebo se jen chcete naučit, jak na to? Jste na správném místě! Tato mini série vám pomůže naučit se vše, co potřebujete k dosažení obojího. Dnes v této části bude naším hlavním cílem a zaměření nastavení pracovního postupu pro vytvoření naší elektronové aplikace. Začneme instalací nezbytných závislostí a devDependencies. Poté nastavíme skripty npm. Nakonec tuto část zakončíme přípravou konfigurací pro Webpack. Nyní začněme!

Jak jsem vytvořil svou první aplikaci Electron &You Can Too, část 1.

Jak jsem vytvořil svou první aplikaci Electron &You Can Too část 3.

Jak jsem vytvořil svou první aplikaci Electron &You Can Too část 4.

Jak jsem vytvořil svou první aplikaci Electron &You Can Too, část 5.

Vše začíná … změnou

To nebylo plánované. Neplánoval jsem ani nepřemýšlel o provedení malé změny tak brzy v projektu. Pokud je však nutné nebo příjemce provést změnu, je lepší to udělat okamžitě, než čekat. Takže, o jaké změně to mluvím? Za prvé, nedělejte si starosti. Naším cílem je stále vytvořit jednoduchou elektronovou aplikaci, která nám pomůže procvičit metodu Grease the Groove, kterou jsme probrali v prvním díle. Tato změna se týká technologického zásobníku, který jsem se rozhodl použít k vytvoření této elektronové aplikace.

Aby byla povídka kratší, nepoužijeme Parcel bundler. Ano, začalo se to trochu obracet. Místo toho použijeme Webpack. Tento balíček udělal velký pokrok, zejména ve verzi 4, která bude brzy vydána. Je rychlejší a ve verzi 4 již nebude potřeba konfigurační soubor a bude ještě rychlejší. To je první důvod. Druhým důvodem je, že jsem narazil na nějaké problémy se sestavením stabilní konfigurace, díky které by Parcel fungoval s Electronem, zejména u sestavení.

Důvod číslo tři je ten, že paradoxně bylo snazší dát dohromady jednoduché konfigurační soubory, díky kterým by Webpack fungoval s Electronem. Z tohoto důvodu jsem se rozhodl vypustit Parcel a přejít na Webpack. Pak je tu ještě jedna věc. V první části jsem si nebyl jistý, zda použít elektron-builder nebo elektron-balič k vytvoření naší elektronové aplikace. Vítězem se stává elektron-balič. Zdálo se mi, že práce s elektronovým baličem je jednodušší. Uvidíme. A to je vše pro změny.

Sestavení podkladů a předpokladů

To byla krátká poznámka o některých změnách projektu. Nyní je čas dát dohromady všechny předpoklady a aktiva, která budeme potřebovat k vytvoření naší elektronové aplikace. To je nejlepší udělat co nejdříve. V opačném případě bychom mohli během vývojové fáze narazit na nějaké problémy. To není nejlepší čas na řešení těchto typů problémů. Takže se ujistěte, že máme nainstalované a připravené všechny knihovny a pluginy. Naše elektronová aplikace jich bude vyžadovat několik.

Instalace závislostí

Začněme závislostmi. Budeme potřebovat čtyři závislosti. Tyto závislosti jsou elektron, reakce, reakce-dom a čtvrtá jsou stylizované složky. Každou z nich lokálně stáhneme a nainstalujeme. Mou preferovanou volbou je jako obvykle příze. Můžete si však vybrat správce balíčků, kterého rádi používáte a s nímž pracujete, přízi, npm, pnpm nebo něco jiného. Mějte na paměti, že se jedná o závislosti, nikoli o devDependencies. Takže nepoužívejte příznak „-D“ nebo „–save-dev“.

yarn add electron react react-dom styled-components

nebo

npm install electron react react-dom styled-components

nebo

pnpm install electron react react-dom styled-components

Instalace devDependencies

Dále, když máme všechny potřebné závislosti, je čas stáhnout a nainstalovat devDependencies. K sestavení naší elektronové aplikace budeme opět potřebovat jedenáct devDependencies. Jsou to babel-core, babel-loader, babel-preset-env, babel-preset-react, babili-webpack-plugin, electron-packager, extract-text-webpack-plugin, file-loader, html-webpack-plugin, webpack a webpack-dev-server. Pojďme je nainstalovat. Nyní můžete použít příznak „-D“ nebo „–save-dev“.

yarn add -D babel-core babel-loader babel-preset-env babel-preset-react babili-webpack-plugin electron-packager extract-text-webpack-plugin file-loader html-webpack-plugin webpack webpack-dev-server

nebo

npm install -D babel-core babel-loader babel-preset-env babel-preset-react babili-webpack-plugin electron-packager extract-text-webpack-plugin file-loader html-webpack-plugin webpack webpack-dev-server

nebo

pnpm install -D babel-core babel-loader babel-preset-env babel-preset-react babili-webpack-plugin electron-packager extract-text-webpack-plugin file-loader html-webpack-plugin webpack webpack-dev-server
"dependencies": {
  "electron": "^1.7.11",
  "react": "^16.2.0",
  "react-dom": "^16.2.0",
  "styled-components": "^3.1.6"
},
"devDependencies": {
  "babel-core": "^6.26.0",
  "babel-loader": "^7.1.2",
  "babel-preset-env": "^1.6.1",
  "babel-preset-react": "^6.24.1",
  "babili-webpack-plugin": "^0.1.2",
  "electron-packager": "^10.1.2",
  "extract-text-webpack-plugin": "^3.0.2",
  "file-loader": "^1.1.6",
  "html-webpack-plugin": "^2.30.1",
  "webpack": "^3.10.0",
  "webpack-dev-server": "^2.11.1"
}

Rychlá poznámka k verzím:budeme používat nejnovější verze závislostí a devDependencies. Postupem času však tyto verze zastarají. Použijte požadované verze, pravděpodobně nejnovější v době, kdy čtete tento článek. Pokud narazíte na nějaké problémy a něco nebude fungovat, jak by mělo, zkuste downgradovat své závislosti a devDependencies na verze výše. Může se stát, že dojde k nějaké zlomové změně, která poruší kód. V tom případě mě neváhejte kontaktovat a dejte mi o tom vědět.

Skripty a soubor package.json

Díky tomu jsme téměř připraveni začít pracovat a vyvíjet naši elektronovou aplikaci. Než to však uděláme, musíme vytvořit řadu jednoduchých skriptů npm. Nejprve potřebujeme skript, který nám umožní spustit aplikaci v režimu „dev“. Za druhé, měli bychom také přidat skript pro spuštění naší aplikace v produkčním režimu. Za třetí, potřebujeme skript, který vytvoří podklady pro naši aplikaci. Za čtvrté, skript, který zabalí naši aplikaci.

Nakonec ještě jeden skript, který vezme tento balíček a použije electron-packager k vytvoření sestavení, které můžeme spustit bez příkazového řádku. Tyto skripty budou velmi snadné a budou používat některá smysluplná jména, jako například „build“, „dev“, „package“, „postpackage“ a „prod“.

"scripts": {
  "build": "webpack --config webpack.build.config.js",
  "dev": "webpack-dev-server --hot --host 0.0.0.0 --config=./webpack.dev.config.js",
  "package": "webpack --config webpack.build.config.js",
  "postpackage": "electron-packager ./ --out=./builds",
  "prod": "webpack --config webpack.build.config.js && electron --noDevServer ."
}

Kromě těchto skriptů bychom také měli přidat některé další informace, jako je „název“, „verze“, „popis“, „licence“, „soukromé“, „úložiště“, „domovská stránka“, „chyby“, „autor“ , „motory“ a „hlavní“. Mějte prosím na paměti, že ne všechny tyto informace jsou nutné nebo povinné. Přidání všech výše uvedených je jen zvyk. Pokud si nejste jisti, zda je vaše package.json platí, můžete udělat dvě věci.

Nejprve zkuste nainstalovat závislosti a devDependencies. Neplatné package.json vyhodí chybu. Za druhé, použijte jednoduchý online validátor. Nějaké základní package.json může vypadat jako příklad níže. Neváhejte si jej přizpůsobit a použít nebo si vytvořit vlastní.

{
  "name": "grease-the-groove-app",
  "version": "0.0.1",
  "description": "Electron app to help you practice Grease the Groove method to achieve your goals and get stronger 💪!",
  "license": "MIT",
  "private": false,
  "repository": {
    "type": "git",
    "url": "https://url.git"
  },
  "homepage": "https://url#readme",
  "bugs": {
    "url": "https://url/issues"
  },
  "author": {
    "name": "Your name",
    "email": "[email protected]",
    "url": "https://url.com/"
  },
  "engines": {
    "node": ">=9.0.0",
    "npm": ">=5.0.0",
    "yarn": ">=1.0.0"
  },
  "main": "main.js",
  "scripts": {
    "build": "webpack --config webpack.build.config.js",
    "dev": "webpack-dev-server --hot --host 0.0.0.0 --config=./webpack.dev.config.js",
    "package": "webpack --config webpack.build.config.js",
    "postpackage": "electron-packager ./ --out=./builds",
    "prod": "webpack --config webpack.build.config.js && electron --noDevServer ."
  },
  "dependencies": {
    "electron": "^1.7.11",
    "react": "^16.2.0",
    "react-dom": "^16.2.0",
    "styled-components": "^3.1.6"
  },
  "devDependencies": {
    "babel-core": "^6.26.0",
    "babel-loader": "^7.1.2",
    "babel-preset-env": "^1.6.1",
    "babel-preset-react": "^6.24.1",
    "babili-webpack-plugin": "^0.1.2",
    "electron-packager": "^10.1.2",
    "extract-text-webpack-plugin": "^3.0.2",
    "file-loader": "^1.1.6",
    "html-webpack-plugin": "^2.30.1",
    "webpack": "^3.10.0",
    "webpack-dev-server": "^2.11.1"
  }
}

Rychlá poznámka k poli verze:Rád začínám každý projekt s verzí „0.0.1“ a měním verzi „patch“, jak postupuji vývojovou fází. Poté, když je projekt připraven na první oficiální vydání, změním verzi na „1.0.0“. Opět je to jen můj zvyk. Mějte na paměti, že pokud nechcete, tento proces verzování nemusíte následovat ani jej používat. Používejte jakoukoli verzi, která se vám líbí a která je pro vás pohodlná.

Různé soubory

Poslední věc. Potřebujeme nějakou ikonu. Naše elektronová aplikace se bude moci schovat do systémové lišty, když ji uživatel minimalizuje. Jak si možná pamatujete, byla to jedna z nezbytných funkcí, o kterých jsme hovořili v prvním díle. Stručně řečeno, naším cílem je, aby aplikace byla nenápadná a nezatěžovala pracovní plochu uživatele dalším otevřeným oknem. To však také znamená, že budeme potřebovat nějakou ikonu. V opačném případě uživatelé nebudou moci obnovit aplikaci ze systémové lišty. Nebudou to moci vidět. Takže si vyberte, kupte nebo vytvořte nějakou ikonu, která se vám líbí.

Struktura projektu a HTML

Než se dostaneme k nastavení konfiguračních souborů pro Webpack, pojďme si rychle probrat strukturu naší elektronové aplikace. Pokud nejste obeznámeni s Webpackem, může vám to pomoci lépe porozumět konfiguracím Webpacku. Přímo v kořenovém adresáři na první úrovni budou čtyři adresáře:builds , dist , node_modules (vytvořeno instalací závislostí a devDependencies) a src .

Potom, také přímo v kořenovém adresáři, bude osm souborů:.babelrc , .editorconfig , main.js, package.json , README.md , webpack.build.config.js , webpack.dev.config.js a yarn.lock (pokud jste nainstalovali závislosti a devDependencies s přízí). Opět platí, že ne všechny tyto soubory jsou nutné. Takže klidně vynechejte .editorconfig a README.md pokud chcete.

Použijeme builds adresář jako cíl pro package a postpackage skripty. Jinými slovy, toto je adresář, kde najdeme sestavení připravená k použití pro naši elektronovou aplikaci. Soubory generované Webpackem budou uloženy na dist . Nakonec src bude naším hlavním adresářem pro vývoj. Uvnitř src budou další dva adresáře, app a assets . assets bude obsahovat ikonu aplikace a jakékoli další položky, které můžeme chtít přidat. app bude obsahovat všechny soubory JavaScript nebo komponenty React, které vytvoříme.

Komponenta React bude uložena v component adresář. Na stejné úrovni, uvnitř app adresáře, vytvoříme také „hlavní“ soubor React s názvem App.jsx a použijte tento soubor k importu a vykreslení všech komponent pro naši elektronovou aplikaci. Přímo uvnitř src bude také index.js , soubor, kde vykreslíme hlavní komponentu React, App definováno v App.jsx . Doufám, že to stále dává alespoň trochu smysl. Použijme raději rychlou „ilustraci“:

grease-the-groove-app
├── builds
├── dist
├── node_modules
├── src
│   └── app
│       └── components
│       └── App.jsx
│   └── assets
│       └── grease-the-groove-icon.ico
│       └── grease-the-groove-icon.png
│       └── grease-the-groove-icon.svg
│   └── index.js
├── .babelrc
├── .editorconfig
├── main.js
├── package.json
├── README.md
├── webpack.build.config.js
├── webpack.dev.config.js
└── yarn.lock

Rychlá poznámka k HTML:Možná jste si všimli, že neexistuje žádný index.html nebo jakýkoli jiný soubor HTML. Nejedná se o chybu ani překlep. Budeme používat HtmlWebpackPlugin bez HTML šablony. Necháme Webpack, aby vytvořil tento soubor pro použití a uložil jej do dist adresář.

Příprava webového balíčku

Nyní dokončíme tuto přípravnou fázi a náš pracovní postup sestavením dvou jednoduchých konfigurací Webpacku. Jednu konfiguraci použijeme pro vývoj a druhou pro výrobu, případně balení a stavbu naší elektronové aplikace. Pravděpodobně největší rozdíl mezi těmito konfiguracemi je ten, že ta pro vývoj bude využívat devServer a devtool zatímco ten pro výrobu nebude. Dalším rozdílem je, že konfigurace pro produkci bude používat BabiliPlugin .

Kromě těchto dvou rozdílů budou naše konfigurace Webpack v podstatě stejné. Použijeme stejný rules (pro jsx soubory, obrázky a písma), adresáře, soubory, entry , output target , resolve stejně jako pluginy (kromě BabiliPlugin ). Pojďme se podívat na konečnou podobu a tvar našich konfigurací Webpack. Opět nejprve nakonfigurujte webpack.dev.config.js bude pro rozvoj. Druhý, webpack.build.config.js bude pro výrobu nebo balení a stavbu naší elektronové aplikace.

webpack.dev.config.js:

const webpack = require('webpack')
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const { spawn } = require('child_process')

// Config directories
const SRC_DIR = path.resolve(__dirname, 'src')
const OUTPUT_DIR = path.resolve(__dirname, 'dist')

// Any directories you will be adding code/files into, need to be added to this array so Webpack will pick them up
const defaultInclude = [SRC_DIR]

module.exports = {
  entry: SRC_DIR + '/index.js',
  output: {
    path: OUTPUT_DIR,
    publicPath: '/',
    filename: 'bundle.js'
  },
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        use: [{ loader: 'babel-loader' }],
        include: defaultInclude
      },
      {
        test: /\.(jpe?g|png|gif|ico)$/,
        use: [{ loader: 'file-loader?name=img/[name]__[hash:base64:5].[ext]' }],
        include: defaultInclude
      },
      {
        test: /\.(eot|svg|ttf|woff|woff2)$/,
        use: [{ loader: 'file-loader?name=font/[name]__[hash:base64:5].[ext]' }],
        include: defaultInclude
      }
    ]
  },
  resolve: {
    extensions: ['.js', '.jsx'],
  },
  target: 'electron-renderer',
  plugins: [
    new HtmlWebpackPlugin(),
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify('development')
    })
  ],
  devtool: 'cheap-source-map',
  devServer: {
    contentBase: OUTPUT_DIR,
    stats: {
      colors: true,
      chunks: false,
      children: false
    },
    before() {
      spawn(
        'electron',
        ['.'],
        { shell: true, env: process.env, stdio: 'inherit' }
      )
      .on('close', code => process.exit(0))
      .on('error', spawnError => console.error(spawnError))
    }
  }
}

webpack.build.config.js:

const webpack = require('webpack')
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const BabiliPlugin = require('babili-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')

// Config directories
const SRC_DIR = path.resolve(__dirname, 'src')
const OUTPUT_DIR = path.resolve(__dirname, 'dist')

// Any directories you will be adding code/files into, need to be added to this array so Webpack will pick them up
const defaultInclude = [SRC_DIR]

module.exports = {
  entry: SRC_DIR + '/index.js',
  output: {
    path: OUTPUT_DIR,
    publicPath: './',
    filename: 'bundle.js'
  },
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        use: [{ loader: 'babel-loader' }],
        include: defaultInclude
      },
      {
        test: /\.(jpe?g|png|gif|ico)$/,
        use: [{ loader: 'file-loader?name=img/[name]__[hash:base64:5].[ext]' }],
        include: defaultInclude
      },
      {
        test: /\.(eot|svg|ttf|woff|woff2)$/,
        use: [{ loader: 'file-loader?name=font/[name]__[hash:base64:5].[ext]' }],
        include: defaultInclude
      }
    ]
  },
  resolve: {
    extensions: ['.js', '.jsx'],
  },
  target: 'electron-renderer',
  plugins: [
    new HtmlWebpackPlugin(),
    new ExtractTextPlugin('bundle.css'),
    new webpack.DefinePlugin({
      'process.env.NODE_ENV': JSON.stringify('production')
    }),
    new BabiliPlugin()
  ],
  stats: {
    colors: true,
    children: false,
    chunks: false,
    modules: false
  }
}

Závěrečné úvahy o budování elektronové aplikace

Toto je konec tohoto, druhého dílu této mini série. Může se to zdát málo. Nakonec jsme pracovali pouze na workflow pro tento projekt. Měli bychom však mít na paměti, že práce, kterou jsme dnes odvedli, nebyla bezvýznamná ani ztráta času. Odvedli jsme slušný kus práce, který nám pomůže do budoucna. Jak? Celá tato práce, nastavení pracovního postupu, kterou jsme dnes udělali, pomůže vytvořit naši elektronovou aplikaci rychleji a snadněji. Byla to cenná investice, která nám přinese užitek později.

Vím, že v první části jsem vám slíbil, že se dostaneme do kódu. Jistě, tu a tam byl nějaký kód, alespoň na konci, když jsme vytvářeli ty konfigurace pro Webpack. Stále jsme však nepracovali na naší elektronové aplikaci. Přesto doufám, že se vám tento díl líbil. A do budoucna? Nedělejte si starosti. To se již nebude opakovat, protože nyní jsme připraveni tento projekt uvést do provozu. V další části tedy skočíme přímo do vývojové fáze a začneme psát první řádky kódu pro naši elektronovou aplikaci.