├── .circleci └── config.yml ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── babel.config.js ├── commitlint.config.js ├── husky.config.js ├── jest.config.js ├── meta.js ├── package.json ├── template ├── .babelrc ├── .electron-vue │ ├── build.config.js │ ├── build.js │ ├── dev-client.js │ ├── dev-runner.js │ ├── webpack.main.config.js │ ├── webpack.renderer.config.js │ └── webpack.web.config.js ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── LICENSE ├── README.md ├── build │ └── icons │ │ ├── 256x256.png │ │ ├── icon.icns │ │ └── icon.ico ├── dist │ ├── electron │ │ └── .gitkeep │ └── web │ │ └── .gitkeep ├── package.json ├── src │ ├── index.ejs │ ├── main │ │ ├── index.dev.js │ │ └── index.js │ └── renderer │ │ ├── App.vue │ │ ├── assets │ │ ├── .gitkeep │ │ └── logo.png │ │ ├── components │ │ ├── LandingPage.vue │ │ └── LandingPage │ │ │ └── SystemInformation.vue │ │ ├── main.js │ │ ├── router │ │ └── index.js │ │ └── store │ │ ├── index.js │ │ └── modules │ │ ├── Counter.js │ │ └── index.js ├── static │ └── .gitkeep └── test │ ├── .eslintrc │ ├── e2e │ ├── index.js │ ├── specs │ │ └── Launch.spec.js │ └── utils.js │ └── unit │ ├── index.js │ ├── karma.conf.js │ └── specs │ └── LandingPage.spec.js ├── test └── index.test.js ├── utils └── index.js └── yarn.lock /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | docker: 5 | - image: circleci/node 6 | steps: 7 | # Checkout repository 8 | - checkout 9 | 10 | # Restore cache 11 | - restore_cache: 12 | key: yarn-cache-{{ checksum "yarn.lock" }} 13 | 14 | # Install dependencies 15 | - run: 16 | name: Install Dependencies 17 | command: NODE_ENV=dev yarn 18 | 19 | # Keep cache 20 | - save_cache: 21 | key: yarn-cache-{{ checksum "yarn.lock" }} 22 | paths: 23 | - "node_modules" 24 | 25 | # Lint 26 | - run: 27 | name: Lint 28 | command: yarn lint 29 | 30 | # Tests 31 | - run: 32 | name: Tests 33 | command: yarn jest 34 | 35 | # Coverage 36 | - run: 37 | name: Coverage 38 | command: yarn codecov 39 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_size = 2 6 | indent_style = space 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | # Common 2 | node_modules 3 | dist 4 | coverage 5 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parserOptions: { 4 | parser: 'babel-eslint', 5 | sourceType: 'module' 6 | }, 7 | env: { 8 | browser: true, 9 | node: true, 10 | 'jest/globals': true 11 | }, 12 | extends: [ 13 | 'standard', 14 | 'plugin:import/errors', 15 | 'plugin:import/warnings', 16 | 'plugin:vue/recommended' 17 | ], 18 | plugins: [ 19 | 'jest', 20 | 'vue' 21 | ], 22 | settings: { 23 | 'import/resolver': { 24 | node: { extensions: ['.js', '.mjs'] } 25 | } 26 | }, 27 | rules: { 28 | // Allow paren-less arrow functions 29 | 'arrow-parens': 0, 30 | // Allow async-await 31 | 'generator-star-spacing': 0, 32 | // Allow debugger during development 33 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0, 34 | // Do not allow console.logs etc... 35 | 'no-console': 0 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.iml 3 | .idea 4 | *.log* 5 | .vscode 6 | .DS_Store 7 | coverage 8 | dist 9 | package-lock.json 10 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. 4 | 5 | ### [1.1.4](https://github.com/kdydesign/vue-electron/compare/v1.1.2...v1.1.4) (2020-12-29) 6 | 7 | 8 | ### Bug Fixes 9 | 10 | * electron store app error ([4d771e6](https://github.com/kdydesign/vue-electron/commit/4d771e69b654fa7d5bdb3e033dda02afa97fc5ab)) 11 | * eslint airbnb fixed ([0ca2bbc](https://github.com/kdydesign/vue-electron/commit/0ca2bbc42033989daf580a1e3f430f6be7be30db)) 12 | * eslint airbnb fixed ([1098a3a](https://github.com/kdydesign/vue-electron/commit/1098a3a53d0170c1dffd69707b3dfda393722b8a)) 13 | * fixed electron-packager platform build error ([4e862c7](https://github.com/kdydesign/vue-electron/commit/4e862c7aae6b08912d7189dab870a78e60f160e3)) 14 | * vuetify Multiple instance ([592fdb2](https://github.com/kdydesign/vue-electron/commit/592fdb2e71b16444ca81194503a5ebcea241db63)) 15 | 16 | ### [1.1.3](https://github.com/kdydesign/vue-electron/compare/v1.1.2...v1.1.3) (2020-05-20) 17 | 18 | #### ❤️ Modular Upgrade 19 | 20 | |Name|Old|New| 21 | |-------------------------------------|---------|----------| 22 | | ajv | ^6.12.2 | ^7.0.2 | 23 | | @babel/core | ^7.9.6 | ^7.12.10 | 24 | | @babel/preset-env | ^7.9.6 | ^7.12.11 | 25 | | @babel/plugin-transform-runtime | ^7.9.6 | ^7.12.10 | 26 | | @babel/preset-react | ^7.9.4 | ^7.12.10 | 27 | | @quasar/extras | ^1.8.1 | ^1.9.12 | 28 | | quasar | ^1.11.3 | ^1.14.7 | 29 | | vuetify | ^2.2.29 | ^2.4.0 | 30 | | babel-loader | ^8.1.0 | ^8.2.2 | 31 | | cfonts | ^2.8.2 | ^2.9.1 | 32 | | chalk | ^4.0.0 | ^4.1.0 | 33 | | copy-webpack-plugin | ^6.0.1 | ^6.2.1 | 34 | | cross-env | ^7.0.2 | ^7.0.3 | 35 | | css-loader | ^3.5.3 | ^5.0.1 | 36 | | electron | ^9.0.0 | ^11.1.1 | 37 | | electron-devtools-installer | ^3.0.0 | ^3.1.1 | 38 | | electron-packager | ^14.2.1 | ^15.2.0 | 39 | | electron-rebuild | ^1.11.0 | ^2.3.4 | 40 | | electron-builder | ^22.6.1 | ^22.9.1 | 41 | | eslint | ^7.0.0 | ^7.16.0 | 42 | | eslint-plugin-html | ^6.0.2 | ^6.1.1 | 43 | | eslint-config-standard | ^14.1.1 | ^16.0.2 | 44 | | eslint-plugin-import | ^2.20.2 | ^2.22.1 | 45 | | eslint-plugin-vue | ^6.2.2 | ^7.4.0 | 46 | | eslint-config-airbnb-base | ^14.1.0 | ^14.2.1 | 47 | | eslint-import-resolver-webpack | ^0.12.1 | ^0.13.0 | 48 | | file-loader | ^6.0.0 | ^6.2.0 | 49 | | html-webpack-plugin | ^4.3.0 | ^4.5.0 | 50 | | karma | ^5.0.9 | ^5.2.3 | 51 | | karma-coverage | ^2.0.2 | ^2.0.3 | 52 | | spectron | ^11.0.0 | ^13.0.0 | 53 | | mocha | ^7.1.2 | ^8.2.1 | 54 | | node-sass | ^4.14.1 | ^5.0.0 | 55 | | sass-loader | ^8.0.2 | ^10.1.0 | 56 | | less | ^3.11.1 | ^4.0.0 | 57 | | less-loader | ^6.1.0 | ^7.2.0 | 58 | | style-loader | ^1.2.1 | ^2.0.0 | 59 | | url-loader | ^4.1.0 | ^4.1.1 | 60 | | vue-loader | ^15.9.2 | ^15.9.6 | 61 | | webpack-cli | ^3.3.11 | ^4.3.0 | 62 | | axios | ^0.19.2 | ^0.21.1 | 63 | | vue-router | ^3.2.0 | ^3.4.9 | 64 | | vue | ^2.6.11 | ^2.6.12 | 65 | | vuex | ^3.4.0 | ^3.6.0 | 66 | | terser-webpack-plugin | ^3.0.1 | ^4.2.3 | 67 | | vue-template-compiler | ^2.6.11 | ^2.6.12 | 68 | 69 | 70 | ### [1.1.2](https://github.com/kdydesign/vue-electron/compare/v1.1.1...v1.1.2) (2020-05-20) 71 | 72 | #### ❤️ Modular Upgrade 73 | 74 | |Name|Old|New| 75 | |-------------------------------------|-------------|---------| 76 | | ajv | ^6.10.2 | ^6.12.2 | 77 | | @babel/core | ^7.7.7 | ^7.9.6 | 78 | | @babel/preset-env | ^7.7.7 | ^7.9.6 | 79 | | @babel/plugin-syntax-dynamic-import | ^7.7.4 | ^7.8.3 | 80 | | @babel/plugin-transform-runtime | ^7.7.6 | ^7.9.6 | 81 | | @babel/preset-react | ^7.7.4 | ^7.9.4 | 82 | | @quasar/extras | ^1.3.3 | ^1.8.1 | 83 | | quasar | ^1.5.11 | ^1.11.3 | 84 | | vuetify | ^2.1.15 | ^2.2.29 | 85 | | babel-loader | ^8.0.6 | ^8.1.0 | 86 | | cfonts | ^2.4.5 | ^2.8.2 | 87 | | chalk | ^3.0.0 | ^4.0.0 | 88 | | copy-webpack-plugin | ^5.1.1 | ^6.0.1 | 89 | | cross-env | ^6.0.3 | ^7.0.2 | 90 | | css-loader | ^3.4.0 | ^3.5.3 | 91 | | electron | ^7.1.7 | ^9.0.0 | 92 | | electron-devtools-installer | ^2.2.4 | ^3.0.0 | 93 | | electron-packager | ^14.1.1 | ^14.2.1 | 94 | | electron-rebuild | ^1.8.8 | ^1.11.0 | 95 | | electron-builder | ^21.2.0 | ^22.6.1 | 96 | | babel-eslint | ^10.0.3 | ^10.1.0 | 97 | | eslint | ^6.8.0 | ^7.0.0 | 98 | | eslint-loader | ^3.0.3 | ^4.0.2 | 99 | | eslint-plugin-html | ^6.0.0 | ^6.0.2 | 100 | | eslint-config-standard | ^14.1.0 | ^14.1.1 | 101 | | eslint-plugin-import | ^2.19.1 | ^2.20.2 | 102 | | eslint-plugin-node | ^10.0.0 | ^11.1.0 | 103 | | eslint-plugin-vue | ^6.0.2 | ^6.2.2 | 104 | | eslint-config-airbnb-base | ^14.0.0 | ^14.1.0 | 105 | | eslint-import-resolver-webpack | ^0.12.0 | ^0.12.1 | 106 | | file-loader | ^5.0.2 | ^6.0.0 | 107 | | html-webpack-plugin | ^3.2.0 | ^4.3.0 | 108 | | karma | ^4.4.1 | ^5.0.9 | 109 | | karma-coverage | ^2.0.1 | ^2.0.2 | 110 | | karma-mocha | ^1.3.0 | ^2.0.1 | 111 | | spectron | ^9.0.0 | ^11.0.0 | 112 | | mocha | ^6.2.2 | ^7.1.2 | 113 | | node-sass | ^4.13.0 | ^4.14.1 | 114 | | sass-loader | ^8.0.0 | ^8.0.2 | 115 | | less | ^3.10.3 | ^3.11.1 | 116 | | less-loader | ^5.0.0 | ^6.1.0 | 117 | | style-loader | ^1.1.2 | ^1.2.1 | 118 | | url-loader | ^3.0.0 | ^4.1.0 | 119 | | vue-loader | ^15.8.3 | ^15.9.2 | 120 | | webpack | ^4.41.4 | ^4.43.0 | 121 | | webpack-cli | ^3.3.10 | ^3.3.11 | 122 | | webpack-dev-server | ^3.10.1 | ^3.11.0 | 123 | | axios | ^0.19.0 | ^0.19.2 | 124 | | vue-router | ^3.1.3 | ^3.2.0 | 125 | | vuex | ^3.1.2 | ^3.4.0 | 126 | 127 | 128 | ## [1.1.1](https://github.com/kdydesign/vue-electron/compare/v1.0.1...v1.1.1) (2020-01-15)| 129 | ### [1.0.1](https://github.com/kdydesign/vue-electron/compare/v1.1.0...v1.0.1) (2020-01-15) 130 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Dev.DY 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ⚡️ Vue-Electron Boilerplate 2 | ![Version][version-src] 3 | [![Circle CI][circle-ci-src]][circle-ci-href] 4 | [![Codecov][codecov-src]][codecov-href] 5 | [![Standard JS][standard-js-src]][standard-js-href] 6 | ![License][license-src] 7 | 8 | > An Electron & Vue.js quick start boilerplate with vue-cli support 9 | 10 | ## Infos 11 | - [📖 **Release Notes**](./CHANGELOG.md) 12 | 13 | ## Getting Started 14 | 15 | ```bash 16 | # Install vue-cli and scaffold boilerplate 17 | $ npm install -g @vue/cli 18 | $ npm install -g @vue/cli-init 19 | 20 | $ vue init kdydesign/vue-electron my-project 21 | $ cd my-project 22 | $ npm install 23 | $ npm run dev 24 | ``` 25 | 26 | ## About Main Modules 27 | vue-electron keeps core dependency modules up to date. 28 | 29 | ### ❤️ Core 30 | 31 | | Module | Version | 32 | |----------|------------------| 33 | | **Electron** | **11.x** ![new][new-src] | 34 | | Vue-CLI | 3.x | 35 | | Vue | 2.x | 36 | | Babel | 7.x | 37 | 38 | ### 🔱 CSS-Preprocessor 39 | 40 | | Module | Version | 41 | |--------|------------------| 42 | | Sass | 5.x | 43 | | Less | 4.x | 44 | | Stylus | 0.54.x | 45 | 46 | ### ⭐️ Framework 47 | 48 | | Module | Version | 49 | |--------|------------------| 50 | | Quasar | 1.14.x | 51 | | vuetify| 2.4.x | 52 | 53 | 54 | ## License 55 | 56 | [MIT License](./LICENSE) 57 | 58 | Copyright (c) [Dev.DY](https://kdydesign.github.io/) 59 | 60 | 61 | [version-src]: https://img.shields.io/github/package-json/v/kdydesign/vue-electron?style=flat-square 62 | [circle-ci-src]: https://img.shields.io/circleci/project/github/kdydesign/vue-electron/master.svg?style=flat-square 63 | [circle-ci-href]: https://circleci.com/gh/kdydesign/vue-electron/tree/master 64 | [codecov-src]: https://img.shields.io/codecov/c/github/kdydesign/vue-electron.svg?style=flat-square 65 | [codecov-href]: https://codecov.io/gh/kdydesign/vue-electron 66 | [david-dm-src]: https://david-dm.org/kdydesign/vue-electron/status.svg?style=flat-square 67 | [david-dm-href]: https://david-dm.org/kdydesign/vue-electron 68 | [standard-js-src]: https://img.shields.io/badge/code_style-standard-brightgreen.svg?style=flat-square 69 | [standard-js-href]: https://standardjs.com 70 | [license-src]: https://img.shields.io/github/license/kdydesign/vue-electron?style=flat-square 71 | [new-src]: https://img.shields.io/badge/-new-blue?style=flat-square 72 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | '@babel/preset-env', { 5 | targets: { 6 | esmodules: true 7 | } 8 | } 9 | ] 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: [ 3 | '@commitlint/config-conventional' 4 | ] 5 | } -------------------------------------------------------------------------------- /husky.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | hooks: { 3 | 'commit-msg': 'commitlint -E HUSKY_GIT_PARAMS', 4 | 'pre-commit': 'yarn lint', 5 | 'pre-push': 'yarn lint' 6 | } 7 | } -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | collectCoverage: true, 3 | modulePathIgnorePatterns: ['template'], 4 | collectCoverageFrom: ['template/**/*.js'], 5 | testEnvironment: 'node' 6 | } 7 | -------------------------------------------------------------------------------- /meta.js: -------------------------------------------------------------------------------- 1 | const { join } = require('path') 2 | const { 3 | sortDependencies, 4 | installDependencies, 5 | runLintFix, 6 | printMessage 7 | } = require('./utils') 8 | 9 | module.exports = { 10 | prompts: { 11 | name: { 12 | type: 'string', 13 | required: true, 14 | message: 'Application Name', 15 | default: 'your-app' 16 | }, 17 | appid: { 18 | type: 'string', 19 | required: true, 20 | message: 'Application Id', 21 | default: 'com.example.yourapp' 22 | }, 23 | appver: { 24 | type: 'string', 25 | required: true, 26 | message: 'Application Version', 27 | default: '0.0.1' 28 | }, 29 | description: { 30 | type: 'string', 31 | required: false, 32 | message: 'Project description', 33 | default: 'An electron-vue project' 34 | }, 35 | csspreprocessor: { 36 | type: 'list', 37 | message: 'Select CSS Pre-Processor', 38 | choices: [ 39 | { 40 | name: 'Sass', 41 | value: 'sass' 42 | }, 43 | { 44 | name: 'Less', 45 | value: 'less' 46 | }, 47 | { 48 | name: 'Stylus', 49 | value: 'stylus' 50 | }, 51 | { 52 | name: 'None', 53 | value: 'none' 54 | } 55 | ] 56 | }, 57 | plugins: { 58 | type: 'checkbox', 59 | message: 'Select which Vue plugins to install', 60 | choices: ['axios', 'vue-electron', 'vue-router', 'vuex', 'vuex-electron'], 61 | default: ['axios', 'vue-electron', 'vue-router', 'vuex', 'vuex-electron'] 62 | }, 63 | framework: { 64 | type: 'list', 65 | message: 'Select UI framework package to install', 66 | choices: [ 67 | { 68 | name: 'Vuetify', 69 | value: 'vuetify' 70 | }, 71 | { 72 | name: 'Quasar', 73 | value: 'quasar' 74 | }, 75 | { 76 | name: 'None', 77 | value: 'none' 78 | } 79 | ] 80 | }, 81 | eslint: { 82 | type: 'confirm', 83 | require: true, 84 | message: 'Use linting with ESLint?', 85 | default: true 86 | }, 87 | eslintConfig: { 88 | when: 'eslint', 89 | type: 'list', 90 | message: 'Which ESLint config would you like to use?', 91 | choices: [ 92 | { 93 | name: 'Standard (https://github.com/feross/standard)', 94 | value: 'standard', 95 | short: 'Standard' 96 | }, 97 | { 98 | name: 'Airbnb (https://github.com/airbnb/javascript)', 99 | value: 'airbnb', 100 | short: 'Airbnb' 101 | }, 102 | { 103 | name: 'none (configure it yourself)', 104 | value: 'none', 105 | short: 'none' 106 | } 107 | ] 108 | }, 109 | unit: { 110 | type: 'confirm', 111 | message: 'Set up unit testing with Karma + Mocha?', 112 | required: true 113 | }, 114 | e2e: { 115 | type: 'confirm', 116 | message: 'Set up end-to-end testing with Spectron + Mocha?', 117 | require: true 118 | }, 119 | builder: { 120 | type: 'list', 121 | message: 'What build tool would you like to use?', 122 | choices: [ 123 | { 124 | name: 'electron-builder (https://github.com/electron-userland/electron-builder)', 125 | value: 'builder', 126 | short: 'builder' 127 | }, 128 | { 129 | name: 'electron-packager (https://github.com/electron-userland/electron-packager)', 130 | value: 'packager', 131 | short: 'packager' 132 | } 133 | ] 134 | }, 135 | autoInstall: { 136 | type: 'list', 137 | message: 138 | 'Should we run `npm install` for you after the project has been created? (recommended)', 139 | choices: [ 140 | { 141 | name: 'Yes, use NPM', 142 | value: 'npm', 143 | short: 'npm' 144 | }, 145 | { 146 | name: 'Yes, use Yarn', 147 | value: 'yarn', 148 | short: 'yarn' 149 | }, 150 | { 151 | name: 'No, I will handle that myself', 152 | value: false, 153 | short: 'no' 154 | } 155 | ] 156 | } 157 | }, 158 | helpers: { 159 | isEnabled (list, check, opts) { 160 | if (list[check] || list === check) { 161 | return opts.fn(this) 162 | } else { 163 | return opts.inverse(this) 164 | } 165 | }, 166 | deps (plugins) { 167 | let output = '' 168 | const dependencies = { 169 | axios: '^0.21.1', 170 | 'vue-electron': '^1.0.6', 171 | 'vue-router': '^3.4.9', 172 | vuex: '^3.6.0', 173 | 'vuex-electron': '^1.0.3' 174 | } 175 | 176 | if (Object.keys(plugins).length > 0) output += ',\n' 177 | 178 | Object.keys(plugins).forEach((p, i) => { 179 | output += ` "${p}": "${dependencies[p]}"` 180 | if (i !== Object.keys(plugins).length - 1) output += ',\n' 181 | }) 182 | 183 | return output 184 | }, 185 | depsf (framework) { 186 | let output = '' 187 | 188 | switch (framework) { 189 | case 'vuetify': 190 | output = ', \n "vuetify": "^2.4.0"' 191 | break 192 | case 'quasar': 193 | output = ', \n "quasar": "^1.14.7"' 194 | break 195 | } 196 | 197 | return output 198 | }, 199 | testing (unit, e2e, opts) { 200 | if (unit || e2e) { 201 | return opts.fn(this) 202 | } 203 | } 204 | }, 205 | filters: { 206 | 'src/renderer/routes.js': 'plugins[\'vue-router\']', 207 | 'src/renderer/components/LandingPageView/CurrentPage.vue': 'plugins[\'vue-router\']', 208 | 'src/renderer/router/**/*': 'plugins[\'vue-router\']', 209 | 'src/renderer/store/**/*': 'plugins[\'vuex\']', 210 | 'test/e2e/**/*': 'e2e', 211 | 'test/unit/**/*': 'unit', 212 | '.electron-vue/build.config.js': 'builder === \'packager\'', 213 | 'test/.eslintrc': 'e2e || unit', 214 | '.eslintignore': 'eslint', 215 | '.eslintrc.js': 'eslint', 216 | 'appveyor.yml': 'builder === \'builder\'', 217 | '.travis.yml': 'builder === \'builder\'' 218 | }, 219 | complete (data, { chalk }) { 220 | const green = chalk.green 221 | 222 | sortDependencies(data, green) 223 | 224 | const cwd = join(process.cwd(), data.inPlace ? '' : data.destDirName) 225 | 226 | if (data.autoInstall) { 227 | installDependencies(cwd, data.autoInstall, green) 228 | .then(() => { 229 | return runLintFix(cwd, data, green) 230 | }).then(() => { 231 | printMessage(data, green) 232 | }).catch(e => { 233 | console.log(chalk.red('Error:'), e) 234 | }) 235 | } else { 236 | printMessage(data, chalk) 237 | } 238 | } 239 | } 240 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-electron", 3 | "version": "1.1.4", 4 | "description": "An Electron & Vue.js quick start boilerplate with vue-cli support", 5 | "main": "meta.js", 6 | "homepage": "https://github.com/kdydesign/vue-electron#readme", 7 | "repository": "https://github.com/kdydesign/vue-electron", 8 | "license": "MIT", 9 | "bugs": { 10 | "url": "https://github.com/kdydesign/vue-electron/issues", 11 | "email": "kdydesign@gmail.com" 12 | }, 13 | "scripts": { 14 | "lint": "eslint meta.js", 15 | "test": "yarn lint && jest", 16 | "release": "yarn test && standard-version && git push --follow-tags" 17 | }, 18 | "keywords": [ 19 | "electron", 20 | "vue", 21 | "boilerplate", 22 | "hot", 23 | "reload", 24 | "router", 25 | "vuex", 26 | "resource", 27 | "quasar", 28 | "vuetify" 29 | ], 30 | "contributors": [ 31 | { 32 | "name": "Dev.DY " 33 | } 34 | ], 35 | "devDependencies": { 36 | "@babel/core": "latest", 37 | "@babel/preset-env": "latest", 38 | "@commitlint/cli": "latest", 39 | "@commitlint/config-conventional": "latest", 40 | "babel-eslint": "latest", 41 | "babel-jest": "latest", 42 | "codecov": "latest", 43 | "eslint": "latest", 44 | "eslint-config-standard": "latest", 45 | "eslint-plugin-import": "latest", 46 | "eslint-plugin-jest": "latest", 47 | "eslint-plugin-node": "latest", 48 | "eslint-plugin-promise": "latest", 49 | "eslint-plugin-standard": "latest", 50 | "eslint-plugin-vue": "latest", 51 | "husky": "latest", 52 | "jest": "latest", 53 | "standard-version": "latest" 54 | }, 55 | "engines": { 56 | "node": ">= 12.18.3" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /template/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "comments": false, 3 | "env": { 4 | {{#testing unit e2e}} 5 | "test": { 6 | "presets": [ 7 | [ 8 | "@babel/preset-env", { 9 | "targets": { "node": 12 } 10 | } 11 | ] 12 | ], 13 | "plugins": ["istanbul"] 14 | }, 15 | {{/testing}} 16 | "main": { 17 | "presets": [ 18 | [ 19 | "@babel/preset-env", { 20 | "targets": { "node": 12 } 21 | } 22 | ] 23 | ] 24 | }, 25 | "renderer": { 26 | "presets": [ 27 | [ 28 | "@babel/preset-env", { 29 | "modules": false 30 | } 31 | ] 32 | ] 33 | }, 34 | "web": { 35 | "presets": [ 36 | [ 37 | "@babel/preset-env", { 38 | "modules": false 39 | } 40 | ] 41 | ] 42 | } 43 | }, 44 | "plugins": [ 45 | "@babel/transform-runtime", 46 | "@babel/plugin-syntax-dynamic-import" 47 | ] 48 | } 49 | -------------------------------------------------------------------------------- /template/.electron-vue/build.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | 3 | /** 4 | * `electron-packager` options 5 | * https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-electron-packager.html 6 | */ 7 | module.exports = { 8 | arch: 'x64', 9 | asar: true, 10 | dir: path.join(__dirname, '../'), 11 | icon: path.join(__dirname, '../build/icons/icon'), 12 | ignore: /(^\/(src|test|\.[a-z]+|README|yarn|static|dist\/web))|\.gitkeep/, 13 | out: path.join(__dirname, '../build'), 14 | overwrite: true 15 | } 16 | -------------------------------------------------------------------------------- /template/.electron-vue/build.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | process.env.NODE_ENV = 'production' 4 | 5 | const { say } = require('cfonts') 6 | const chalk = require('chalk') 7 | const del = require('del') 8 | {{#if_eq builder 'packager'}} 9 | const packager = require('electron-packager') 10 | {{else}} 11 | const { spawn } = require('child_process') 12 | {{/if_eq}} 13 | const webpack = require('webpack') 14 | const Multispinner = require('multispinner') 15 | 16 | {{#if_eq builder 'packager'}}const buildConfig = require('./build.config'){{/if_eq}} 17 | const mainConfig = require('./webpack.main.config') 18 | const rendererConfig = require('./webpack.renderer.config') 19 | const webConfig = require('./webpack.web.config') 20 | 21 | const doneLog = chalk.bgGreen.white(' DONE ') + ' ' 22 | const errorLog = chalk.bgRed.white(' ERROR ') + ' ' 23 | const okayLog = chalk.bgBlue.white(' OKAY ') + ' ' 24 | const isCI = process.env.CI || false 25 | 26 | if (process.env.BUILD_TARGET === 'clean') clean() 27 | else if (process.env.BUILD_TARGET === 'web') web() 28 | else build() 29 | 30 | function clean () { 31 | del.sync(['build/*', '!build/icons', '!build/icons/icon.*']) 32 | console.log(`\n${doneLog}\n`) 33 | process.exit() 34 | } 35 | 36 | function build () { 37 | greeting() 38 | 39 | del.sync(['dist/electron/*', '!.gitkeep']) 40 | 41 | const tasks = ['main', 'renderer'] 42 | const m = new Multispinner(tasks, { 43 | preText: 'building', 44 | postText: 'process' 45 | }) 46 | 47 | let results = '' 48 | 49 | m.on('success', () => { 50 | process.stdout.write('\x1B[2J\x1B[0f') 51 | console.log(`\n\n${results}`) 52 | console.log(`${okayLog}take it away ${chalk.yellow('`electron-{{builder}}`')}\n`) 53 | {{#if_eq builder 'packager'}}bundleApp(){{else}}process.exit(){{/if_eq}} 54 | }) 55 | 56 | pack(mainConfig).then(result => { 57 | results += result + '\n\n' 58 | m.success('main') 59 | }).catch(err => { 60 | m.error('main') 61 | console.log(`\n ${errorLog}failed to build main process`) 62 | console.error(`\n${err}\n`) 63 | process.exit(1) 64 | }) 65 | 66 | pack(rendererConfig).then(result => { 67 | results += result + '\n\n' 68 | m.success('renderer') 69 | }).catch(err => { 70 | m.error('renderer') 71 | console.log(`\n ${errorLog}failed to build renderer process`) 72 | console.error(`\n${err}\n`) 73 | process.exit(1) 74 | }) 75 | } 76 | 77 | function pack (config) { 78 | return new Promise((resolve, reject) => { 79 | config.mode = 'production' 80 | webpack(config, (err, stats) => { 81 | if (err) reject(err.stack || err) 82 | else if (stats.hasErrors()) { 83 | let err = '' 84 | 85 | stats.toString({ 86 | chunks: false, 87 | colors: true 88 | }) 89 | .split(/\r?\n/) 90 | .forEach(line => { 91 | err += ` ${line}\n` 92 | }) 93 | 94 | reject(err) 95 | } else { 96 | resolve(stats.toString({ 97 | chunks: false, 98 | colors: true 99 | })) 100 | } 101 | }) 102 | }) 103 | } 104 | 105 | {{#if_eq builder 'packager'}} 106 | function bundleApp () { 107 | buildConfig.mode = 'production' 108 | packager(buildConfig).then((err, appPaths) => { 109 | if (err) { 110 | console.log(`\n${errorLog}${chalk.yellow('`electron-packager`')} says...\n`) 111 | console.log(err + '\n') 112 | } else { 113 | console.log(`\n${doneLog}\n`) 114 | } 115 | }) 116 | } 117 | 118 | {{/if_eq}} 119 | function web () { 120 | del.sync(['dist/web/*', '!.gitkeep']) 121 | webConfig.mode = 'production' 122 | webpack(webConfig, (err, stats) => { 123 | if (err || stats.hasErrors()) console.log(err) 124 | 125 | console.log(stats.toString({ 126 | chunks: false, 127 | colors: true 128 | })) 129 | 130 | process.exit() 131 | }) 132 | } 133 | 134 | function greeting () { 135 | const cols = process.stdout.columns 136 | let text = '' 137 | 138 | if (cols > 85) text = 'lets-build' 139 | else if (cols > 60) text = 'lets-|build' 140 | else text = false 141 | 142 | if (text && !isCI) { 143 | say(text, { 144 | colors: ['yellow'], 145 | font: 'simple3d', 146 | space: false 147 | }) 148 | } else console.log(chalk.yellow.bold('\n lets-build')) 149 | console.log() 150 | } 151 | -------------------------------------------------------------------------------- /template/.electron-vue/dev-client.js: -------------------------------------------------------------------------------- 1 | const hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true') 2 | 3 | hotClient.subscribe(event => { 4 | /** 5 | * Reload browser when HTMLWebpackPlugin emits a new index.html 6 | * 7 | * Currently disabled until jantimon/html-webpack-plugin#680 is resolved. 8 | * https://github.com/SimulatedGREG/electron-vue/issues/437 9 | * https://github.com/jantimon/html-webpack-plugin/issues/680 10 | */ 11 | // if (event.action === 'reload') { 12 | // window.location.reload() 13 | // } 14 | 15 | /** 16 | * Notify `mainWindow` when `main` process is compiling, 17 | * giving notice for an expected reload of the `electron` process 18 | */ 19 | if (event.action === 'compiling') { 20 | document.body.innerHTML += ` 21 | 34 | 35 |
36 | Compiling Main Process... 37 |
38 | ` 39 | } 40 | }) 41 | -------------------------------------------------------------------------------- /template/.electron-vue/dev-runner.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const chalk = require('chalk') 4 | const electron = require('electron') 5 | const path = require('path') 6 | const { say } = require('cfonts') 7 | const { spawn } = require('child_process') 8 | const webpack = require('webpack') 9 | const WebpackDevServer = require('webpack-dev-server') 10 | const webpackHotMiddleware = require('webpack-hot-middleware') 11 | const HtmlWebpackPlugin = require('html-webpack-plugin') 12 | 13 | const mainConfig = require('./webpack.main.config') 14 | const rendererConfig = require('./webpack.renderer.config') 15 | 16 | let electronProcess = null 17 | let manualRestart = false 18 | let hotMiddleware 19 | 20 | function logStats (proc, data) { 21 | let log = '' 22 | 23 | log += chalk.yellow.bold(`┏ ${proc} Process ${new Array((19 - proc.length) + 1).join('-')}`) 24 | log += '\n\n' 25 | 26 | if (typeof data === 'object') { 27 | data.toString({ 28 | colors: true, 29 | chunks: false 30 | }).split(/\r?\n/).forEach(line => { 31 | log += ' ' + line + '\n' 32 | }) 33 | } else { 34 | log += ` ${data}\n` 35 | } 36 | 37 | log += '\n' + chalk.yellow.bold(`┗ ${new Array(28 + 1).join('-')}`) + '\n' 38 | 39 | console.log(log) 40 | } 41 | 42 | function startRenderer () { 43 | return new Promise((resolve, reject) => { 44 | rendererConfig.entry.renderer = [path.join(__dirname, 'dev-client')].concat(rendererConfig.entry.renderer) 45 | rendererConfig.mode = 'development' 46 | const compiler = webpack(rendererConfig) 47 | hotMiddleware = webpackHotMiddleware(compiler, { 48 | log: false, 49 | heartbeat: 2500 50 | }) 51 | 52 | compiler.hooks.compilation.tap('compilation', compilation => { 53 | HtmlWebpackPlugin.getHooks(compilation).beforeEmit.tapAsync('html-webpack-plugin-after-emit', (data, cb) => { 54 | hotMiddleware.publish({ action: 'reload' }) 55 | cb() 56 | }) 57 | }) 58 | 59 | compiler.hooks.done.tap('done', stats => { 60 | logStats('Renderer', stats) 61 | }) 62 | 63 | const server = new WebpackDevServer( 64 | compiler, 65 | { 66 | contentBase: path.join(__dirname, '../'), 67 | quiet: true, 68 | before (app, ctx) { 69 | app.use(hotMiddleware) 70 | ctx.middleware.waitUntilValid(() => { 71 | resolve() 72 | }) 73 | } 74 | } 75 | ) 76 | 77 | server.listen(9080) 78 | }) 79 | } 80 | 81 | function startMain () { 82 | return new Promise((resolve, reject) => { 83 | mainConfig.entry.main = [path.join(__dirname, '../src/main/index.dev.js')].concat(mainConfig.entry.main) 84 | mainConfig.mode = 'development' 85 | const compiler = webpack(mainConfig) 86 | 87 | compiler.hooks.watchRun.tapAsync('watch-run', (compilation, done) => { 88 | logStats('Main', chalk.white.bold('compiling...')) 89 | hotMiddleware.publish({ action: 'compiling' }) 90 | done() 91 | }) 92 | 93 | compiler.watch({}, (err, stats) => { 94 | if (err) { 95 | console.log(err) 96 | return 97 | } 98 | 99 | logStats('Main', stats) 100 | 101 | if (electronProcess && electronProcess.kill) { 102 | manualRestart = true 103 | process.kill(electronProcess.pid) 104 | electronProcess = null 105 | startElectron() 106 | 107 | setTimeout(() => { 108 | manualRestart = false 109 | }, 5000) 110 | } 111 | 112 | resolve() 113 | }) 114 | }) 115 | } 116 | 117 | function startElectron () { 118 | var args = [ 119 | '--inspect=5858', 120 | path.join(__dirname, '../dist/electron/main.js') 121 | ] 122 | 123 | // detect yarn or npm and process commandline args accordingly 124 | if (process.env.npm_execpath.endsWith('yarn.js')) { 125 | args = args.concat(process.argv.slice(3)) 126 | } else if (process.env.npm_execpath.endsWith('npm-cli.js')) { 127 | args = args.concat(process.argv.slice(2)) 128 | } 129 | 130 | electronProcess = spawn(electron, args) 131 | 132 | electronProcess.stdout.on('data', data => { 133 | electronLog(data, 'blue') 134 | }) 135 | electronProcess.stderr.on('data', data => { 136 | electronLog(data, 'red') 137 | }) 138 | 139 | electronProcess.on('close', () => { 140 | if (!manualRestart) process.exit() 141 | }) 142 | } 143 | 144 | function electronLog (data, color) { 145 | let log = '' 146 | data = data.toString().split(/\r?\n/) 147 | data.forEach(line => { 148 | log += ` ${line}\n` 149 | }) 150 | if (/[0-9A-z]+/.test(log)) { 151 | console.log( 152 | chalk[color].bold('┏ Electron -------------------') + 153 | '\n\n' + 154 | log + 155 | chalk[color].bold('┗ ----------------------------') + 156 | '\n' 157 | ) 158 | } 159 | } 160 | 161 | function greeting () { 162 | const cols = process.stdout.columns 163 | let text = '' 164 | 165 | if (cols > 104) text = 'electron-vue' 166 | else if (cols > 76) text = 'electron-|vue' 167 | else text = false 168 | 169 | if (text) { 170 | say(text, { 171 | colors: ['yellow'], 172 | font: 'simple3d', 173 | space: false 174 | }) 175 | } else console.log(chalk.yellow.bold('\n electron-vue')) 176 | console.log(chalk.blue(' getting ready...') + '\n') 177 | } 178 | 179 | function init () { 180 | greeting() 181 | 182 | Promise.all([startRenderer(), startMain()]) 183 | .then(() => { 184 | startElectron() 185 | }) 186 | .catch(err => { 187 | console.error(err) 188 | }) 189 | } 190 | 191 | init() 192 | -------------------------------------------------------------------------------- /template/.electron-vue/webpack.main.config.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | process.env.BABEL_ENV = 'main' 4 | 5 | const path = require('path') 6 | const { dependencies } = require('../package.json') 7 | const webpack = require('webpack') 8 | 9 | const TerserPlugin = require('terser-webpack-plugin') 10 | 11 | let mainConfig = { 12 | entry: { 13 | main: path.join(__dirname, '../src/main/index.js') 14 | }, 15 | externals: [ 16 | ...Object.keys(dependencies || {}) 17 | ], 18 | module: { 19 | rules: [ 20 | {{#if eslint}} 21 | { 22 | test: /\.(js)$/, 23 | enforce: 'pre', 24 | exclude: /node_modules/, 25 | use: { 26 | loader: 'eslint-loader', 27 | options: { 28 | formatter: require('eslint-friendly-formatter') 29 | } 30 | } 31 | }, 32 | {{/if}} 33 | { 34 | test: /\.js$/, 35 | use: 'babel-loader', 36 | exclude: /node_modules/ 37 | }, 38 | { 39 | test: /\.node$/, 40 | use: 'node-loader' 41 | } 42 | ] 43 | }, 44 | node: { 45 | __dirname: process.env.NODE_ENV !== 'production', 46 | __filename: process.env.NODE_ENV !== 'production' 47 | }, 48 | output: { 49 | filename: '[name].js', 50 | libraryTarget: 'commonjs2', 51 | path: path.join(__dirname, '../dist/electron') 52 | }, 53 | optimization: { 54 | noEmitOnErrors: true // NoEmitOnErrorsPlugin 55 | }, 56 | resolve: { 57 | extensions: ['.js', '.json', '.node'] 58 | }, 59 | target: 'electron-main' 60 | } 61 | 62 | /** 63 | * Adjust mainConfig for development settings 64 | */ 65 | if (process.env.NODE_ENV !== 'production') { 66 | if (mainConfig.plugins === void 0) { 67 | mainConfig.plugins = [] 68 | } 69 | 70 | mainConfig.plugins.push( 71 | new webpack.DefinePlugin({ 72 | '__static': `"${path.join(__dirname, '../static').replace(/\\/g, '\\\\')}"` 73 | }) 74 | ) 75 | } 76 | 77 | /** 78 | * Adjust mainConfig for production settings 79 | */ 80 | if (process.env.NODE_ENV === 'production') { 81 | if (mainConfig.plugins === void 0) { 82 | mainConfig.plugins = [] 83 | } 84 | 85 | mainConfig.optimization = Object.assign(mainConfig.optimization, { 86 | minimize: true, 87 | minimizer: [new TerserPlugin()] 88 | }) 89 | 90 | mainConfig.plugins.push( 91 | new webpack.DefinePlugin({ 92 | 'process.env.NODE_ENV': '"production"' 93 | }) 94 | ) 95 | } 96 | 97 | module.exports = mainConfig 98 | -------------------------------------------------------------------------------- /template/.electron-vue/webpack.renderer.config.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | process.env.BABEL_ENV = 'renderer' 4 | 5 | const path = require('path') 6 | const { dependencies } = require('../package.json') 7 | const webpack = require('webpack') 8 | 9 | const TerserPlugin = require('terser-webpack-plugin') 10 | const CopyWebpackPlugin = require('copy-webpack-plugin') 11 | const MiniCssExtractPlugin = require('mini-css-extract-plugin') 12 | const HtmlWebpackPlugin = require('html-webpack-plugin') 13 | const VueLoaderPlugin = require('vue-loader/lib/plugin') 14 | 15 | /** 16 | * List of node_modules to include in webpack bundle 17 | * 18 | * Required for specific packages like Vue UI libraries 19 | * that provide pure *.vue files that need compiling 20 | * https://simulatedgreg.gitbooks.io/electron-vue/content/en/webpack-configurations.html#white-listing-externals 21 | */ 22 | let whiteListedModules = [ 'vue'{{#if_eq framework 'quasar'}}, 'quasar'{{/if_eq}}{{#if_eq framework 'vuetify'}}, 'vuetify'{{/if_eq}} ] 23 | 24 | let rendererConfig = { 25 | devtool: 'source-map', 26 | entry: { 27 | renderer: path.join(__dirname, '../src/renderer/main.js') 28 | }, 29 | externals: [ 30 | ...Object.keys(dependencies || {}).filter(d => !whiteListedModules.includes(d)) 31 | ], 32 | module: { 33 | rules: [ 34 | { 35 | test: /\.(js|vue)$/, 36 | enforce: 'pre', 37 | exclude: /node_modules/, 38 | use: { 39 | loader: 'eslint-loader', 40 | options: { 41 | formatter: require('eslint-friendly-formatter') 42 | } 43 | } 44 | }, 45 | { 46 | test: /\.styl$/, 47 | use: [MiniCssExtractPlugin.loader, 'css-loader', 'stylus-loader'] 48 | }, 49 | { 50 | test: /\.css$/, 51 | use: [MiniCssExtractPlugin.loader, 'css-loader'] 52 | }, 53 | { 54 | test: /\.html$/, 55 | use: 'vue-html-loader' 56 | }, 57 | { 58 | test: /\.js$/, 59 | use: 'babel-loader', 60 | exclude: /node_modules/ 61 | }, 62 | { 63 | test: /\.node$/, 64 | use: 'node-loader' 65 | }, 66 | { 67 | test: /\.vue$/, 68 | use: { 69 | loader: 'vue-loader', 70 | options: { 71 | extractCSS: process.env.NODE_ENV === 'production', 72 | loaders: { 73 | sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax=1', 74 | scss: 'vue-style-loader!css-loader!sass-loader', 75 | less: 'vue-style-loader!css-loader!less-loader', 76 | styl: 'vue-style-loader!css-loader!stylus-loader' 77 | } 78 | } 79 | } 80 | }, 81 | { 82 | test: /\.(png|jpe?g|gif)$/i, 83 | use: 'file-loader?name=[name].[ext]', 84 | }, 85 | { 86 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/, 87 | loader: 'url-loader', 88 | options: { 89 | limit: 10000, 90 | name: 'media/[name]--[folder].[ext]' 91 | } 92 | }, 93 | { 94 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 95 | use: { 96 | loader: 'url-loader', 97 | options: { 98 | limit: 10000, 99 | name: 'fonts/[name]--[folder].[ext]' 100 | } 101 | } 102 | } 103 | ] 104 | }, 105 | node: { 106 | __dirname: process.env.NODE_ENV !== 'production', 107 | __filename: process.env.NODE_ENV !== 'production' 108 | }, 109 | plugins: [ 110 | new VueLoaderPlugin(), 111 | new MiniCssExtractPlugin({filename: 'styles.css'}), 112 | new HtmlWebpackPlugin({ 113 | filename: 'index.html', 114 | template: path.resolve(__dirname, '../src/index.ejs'), 115 | minify: { 116 | collapseWhitespace: true, 117 | removeAttributeQuotes: true, 118 | removeComments: true 119 | }, 120 | nodeModules: process.env.NODE_ENV !== 'production' 121 | ? path.resolve(__dirname, '../node_modules') 122 | : false 123 | }), 124 | new webpack.HotModuleReplacementPlugin() 125 | ], 126 | optimization: { 127 | noEmitOnErrors: true // NoEmitOnErrorsPlugin 128 | }, 129 | output: { 130 | filename: '[name].js', 131 | libraryTarget: 'commonjs2', 132 | path: path.join(__dirname, '../dist/electron') 133 | }, 134 | resolve: { 135 | alias: { 136 | '@': path.join(__dirname, '../src/renderer'), 137 | 'vue$': 'vue/dist/vue.esm.js' 138 | }, 139 | extensions: ['.js', '.vue', '.json', '.css', '.node'] 140 | }, 141 | target: 'electron-renderer' 142 | } 143 | 144 | /** 145 | * Adjust rendererConfig for development settings 146 | */ 147 | if (process.env.NODE_ENV !== 'production') { 148 | rendererConfig.plugins.push( 149 | new webpack.DefinePlugin({ 150 | '__static': `"${path.join(__dirname, '../static').replace(/\\/g, '\\\\')}"` 151 | }) 152 | ) 153 | } 154 | 155 | /** 156 | * Adjust rendererConfig for production settings 157 | */ 158 | if (process.env.NODE_ENV === 'production') { 159 | rendererConfig.devtool = '' 160 | 161 | rendererConfig.optimization = Object.assign(rendererConfig.optimization, { 162 | minimize: true, 163 | minimizer: [new TerserPlugin()] 164 | }) 165 | 166 | rendererConfig.plugins.push( 167 | new CopyWebpackPlugin({ 168 | patterns: [ 169 | { 170 | from: path.join(__dirname, '../static'), 171 | to: path.join(__dirname, '../dist/electron/static'), 172 | globOptions: { 173 | ignore: ['.*'] 174 | } 175 | } 176 | ] 177 | }), 178 | new webpack.DefinePlugin({ 179 | 'process.env.NODE_ENV': '"production"' 180 | }), 181 | new webpack.LoaderOptionsPlugin({ 182 | minimize: true 183 | }) 184 | ) 185 | } 186 | 187 | module.exports = rendererConfig 188 | -------------------------------------------------------------------------------- /template/.electron-vue/webpack.web.config.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | process.env.BABEL_ENV = 'web' 4 | 5 | const path = require('path') 6 | const webpack = require('webpack') 7 | 8 | const TerserPlugin = require('terser-webpack-plugin') 9 | const CopyWebpackPlugin = require('copy-webpack-plugin') 10 | const MiniCssExtractPlugin = require('mini-css-extract-plugin') 11 | const HtmlWebpackPlugin = require('html-webpack-plugin') 12 | const { VueLoaderPlugin } = require('vue-loader') 13 | 14 | let webConfig = { 15 | devtool: '#cheap-module-eval-source-map', 16 | entry: { 17 | web: path.join(__dirname, '../src/renderer/main.js') 18 | }, 19 | module: { 20 | rules: [ 21 | {{#if eslint}} 22 | { 23 | test: /\.(js|vue)$/, 24 | enforce: 'pre', 25 | exclude: /node_modules/, 26 | use: { 27 | loader: 'eslint-loader', 28 | options: { 29 | formatter: require('eslint-friendly-formatter') 30 | } 31 | } 32 | }, 33 | {{/if}} 34 | {{#if_eq csspreprocessor 'sass'}} 35 | { 36 | test: /\.scss$/, 37 | use: ['vue-style-loader', 'css-loader', 'sass-loader'] 38 | }, 39 | { 40 | test: /\.sass$/, 41 | use: ['vue-style-loader', 'css-loader', 'sass-loader?indentedSyntax'] 42 | }, 43 | {{/if_eq}} 44 | {{#if_eq csspreprocessor 'less'}} 45 | { 46 | test: /\.less$/, 47 | use: ['vue-style-loader', 'css-loader', 'less-loader'] 48 | }, 49 | {{/if_eq}} 50 | {{#if_eq csspreprocessor 'stylus'}} 51 | { 52 | test: /\.css$/, 53 | use: ['vue-style-loader', 'css-loader', 'stylus-loader'] 54 | }, 55 | {{/if_eq}} 56 | { 57 | test: /\.html$/, 58 | use: 'vue-html-loader' 59 | }, 60 | { 61 | test: /\.js$/, 62 | use: 'babel-loader', 63 | include: [ path.resolve(__dirname, '../src/renderer') ], 64 | exclude: /node_modules/ 65 | }, 66 | { 67 | test: /\.vue$/, 68 | use: { 69 | loader: 'vue-loader', 70 | options: { 71 | extractCSS: true, 72 | loaders: { 73 | sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax=1', 74 | scss: 'vue-style-loader!css-loader!sass-loader', 75 | less: 'vue-style-loader!css-loader!less-loader', 76 | styl: 'vue-style-loader!css-loader!stylus-loader' 77 | } 78 | } 79 | } 80 | }, 81 | { 82 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 83 | use: { 84 | loader: 'url-loader', 85 | query: { 86 | limit: 10000, 87 | name: 'imgs/[name].[ext]' 88 | } 89 | } 90 | }, 91 | { 92 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 93 | use: { 94 | loader: 'url-loader', 95 | query: { 96 | limit: 10000, 97 | name: 'fonts/[name].[ext]' 98 | } 99 | } 100 | } 101 | ] 102 | }, 103 | plugins: [ 104 | new VueLoaderPlugin(), 105 | new MiniCssExtractPlugin({filename: 'styles.css'}), 106 | new HtmlWebpackPlugin({ 107 | filename: 'index.html', 108 | template: path.resolve(__dirname, '../src/index.ejs'), 109 | minify: { 110 | collapseWhitespace: true, 111 | removeAttributeQuotes: true, 112 | removeComments: true 113 | }, 114 | nodeModules: false 115 | }), 116 | new webpack.DefinePlugin({ 117 | 'process.env.IS_WEB': 'true' 118 | }), 119 | new webpack.HotModuleReplacementPlugin() 120 | ], 121 | optimization: { 122 | noEmitOnErrors: true // NoEmitOnErrorsPlugin 123 | }, 124 | output: { 125 | filename: '[name].js', 126 | path: path.join(__dirname, '../dist/web') 127 | }, 128 | resolve: { 129 | alias: { 130 | '@': path.join(__dirname, '../src/renderer'), 131 | 'vue$': 'vue/dist/vue.esm.js' 132 | }, 133 | extensions: ['.js', '.vue', '.json', '.css'] 134 | }, 135 | target: 'web' 136 | } 137 | 138 | /** 139 | * Adjust webConfig for production settings 140 | */ 141 | if (process.env.NODE_ENV === 'production') { 142 | webConfig.devtool = '' 143 | 144 | webConfig.optimization = Object.assign(webConfig.optimization, { 145 | minimize: true, 146 | minimizer: [new TerserPlugin()] 147 | }) 148 | 149 | webConfig.plugins.push( 150 | new CopyWebpackPlugin({ 151 | patterns: [ 152 | { 153 | from: path.join(__dirname, '../static'), 154 | to: path.join(__dirname, '../dist/web/static'), 155 | globOptions: { 156 | ignore: ['.*'] 157 | } 158 | } 159 | ] 160 | }), 161 | new webpack.DefinePlugin({ 162 | 'process.env.NODE_ENV': '"production"' 163 | }), 164 | new webpack.LoaderOptionsPlugin({ 165 | minimize: true 166 | }) 167 | ) 168 | } 169 | 170 | module.exports = webConfig 171 | -------------------------------------------------------------------------------- /template/.eslintignore: -------------------------------------------------------------------------------- 1 | {{#testing unit e2e}} 2 | test/unit/coverage/** 3 | test/unit/*.js 4 | test/e2e/*.js 5 | {{/testing}} 6 | -------------------------------------------------------------------------------- /template/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | parserOptions: { 4 | parser: 'babel-eslint', 5 | sourceType: 'module' 6 | }, 7 | env: { 8 | browser: true, 9 | node: true 10 | }, 11 | {{#if_eq eslintConfig 'standard'}} 12 | extends: ['standard', 'plugin:vue/base'], 13 | {{/if_eq}} 14 | {{#if_eq eslintConfig 'airbnb'}} 15 | extends: ['airbnb-base', 'plugin:vue/base'], 16 | {{/if_eq}} 17 | globals: { 18 | __static: true 19 | }, 20 | plugins: [ 21 | 'html', 22 | 'vue' 23 | ], 24 | rules: { 25 | indent: 'off', 26 | 'vue/script-indent': [ 27 | 'warn', 2, { 28 | baseIndent: 1 29 | } 30 | ], 31 | {{#if_eq eslintConfig 'standard'}} 32 | // allow paren-less arrow functions 33 | 'arrow-parens': 0, 34 | // allow async-await 35 | 'generator-star-spacing': 0, 36 | {{/if_eq}} 37 | {{#if_eq eslintConfig 'airbnb'}} 38 | 'global-require': 0, 39 | 'import/no-unresolved': 0, 40 | 'no-param-reassign': 0, 41 | 'no-shadow': 0, 42 | 'import/extensions': 0, 43 | 'import/newline-after-import': 0, 44 | 'no-multi-assign': 0, 45 | 'no-underscore-dangle': 0, 46 | 'import/no-extraneous-dependencies': 0, 47 | 'no-console': 0, 48 | {{/if_eq}} 49 | // allow debugger during development 50 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /template/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | dist/electron/* 3 | dist/web/* 4 | build/* 5 | !build/icons 6 | {{#if unit}} 7 | coverage 8 | {{/if}} 9 | node_modules/ 10 | npm-debug.log 11 | npm-debug.log.* 12 | thumbs.db 13 | !.gitkeep 14 | -------------------------------------------------------------------------------- /template/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Dev.DY 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /template/README.md: -------------------------------------------------------------------------------- 1 | # {{ name }} 2 | 3 | > {{ description }} 4 | 5 | #### Build Setup 6 | 7 | ``` bash 8 | # install dependencies 9 | npm install 10 | 11 | # serve with hot reload at localhost:9080 12 | npm run dev 13 | 14 | # build electron application for production 15 | npm run build 16 | 17 | {{#testing unit e2e}} 18 | # run {{#unit}}unit{{/unit}}{{#unit}}{{#e2e}} & {{/e2e}}{{/unit}}{{#e2e}}end-to-end{{/e2e}} tests 19 | npm test 20 | 21 | {{/testing}} 22 | 23 | {{#if eslint}} 24 | # lint all JS/Vue component files in `src/` 25 | npm run lint 26 | 27 | {{/if}} 28 | ``` 29 | 30 | --- 31 | 32 | This project was generated with [electron-vue](https://github.com/SimulatedGREG/electron-vue) using [vue-cli](https://github.com/vuejs/vue-cli). Documentation about the original structure can be found [here](https://simulatedgreg.gitbooks.io/electron-vue/content/index.html). 33 | -------------------------------------------------------------------------------- /template/build/icons/256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdydesign/vue-electron/5049ea8407b121176edbbd2e8104e2db319839b7/template/build/icons/256x256.png -------------------------------------------------------------------------------- /template/build/icons/icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdydesign/vue-electron/5049ea8407b121176edbbd2e8104e2db319839b7/template/build/icons/icon.icns -------------------------------------------------------------------------------- /template/build/icons/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdydesign/vue-electron/5049ea8407b121176edbbd2e8104e2db319839b7/template/build/icons/icon.ico -------------------------------------------------------------------------------- /template/dist/electron/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdydesign/vue-electron/5049ea8407b121176edbbd2e8104e2db319839b7/template/dist/electron/.gitkeep -------------------------------------------------------------------------------- /template/dist/web/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdydesign/vue-electron/5049ea8407b121176edbbd2e8104e2db319839b7/template/dist/web/.gitkeep -------------------------------------------------------------------------------- /template/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "{{ name }}", 3 | {{#if_eq builder 'packager'}} 4 | "productName": "{{ name }}", 5 | {{/if_eq}} 6 | "version": "{{ appver }}", 7 | "author": "{{ author }}", 8 | "description": "{{ description }}", 9 | "license": "MIT", 10 | "main": "./dist/electron/main.js", 11 | "scripts": { 12 | {{#if_eq builder 'packager'}} 13 | "build": "node .electron-vue/build.js", 14 | "build:darwin": "cross-env BUILD_TARGET=darwin node .electron-vue/build.js", 15 | "build:linux": "cross-env BUILD_TARGET=linux node .electron-vue/build.js", 16 | "build:mas": "cross-env BUILD_TARGET=mas node .electron-vue/build.js", 17 | "build:win32": "cross-env BUILD_TARGET=win32 node .electron-vue/build.js", 18 | {{else}} 19 | "build": "node .electron-vue/build.js && electron-builder", 20 | "build:dir": "node .electron-vue/build.js && electron-builder --dir", 21 | {{/if_eq}} 22 | "build:clean": "cross-env BUILD_TARGET=clean node .electron-vue/build.js", 23 | "build:web": "cross-env BUILD_TARGET=web node .electron-vue/build.js", 24 | "dev": "node .electron-vue/dev-runner.js", 25 | {{#if e2e}} 26 | "e2e": "npm run pack && mocha test/e2e", 27 | {{/if}} 28 | {{#if eslint}} 29 | "lint": "eslint --ext .js,.vue -f ./node_modules/eslint-friendly-formatter src{{#testing unit e2e}} test{{/testing}}", 30 | "lint:fix": "eslint --ext .js,.vue -f ./node_modules/eslint-friendly-formatter --fix src{{#testing unit e2e}} test{{/testing}}", 31 | {{/if}} 32 | "pack": "npm run pack:main && npm run pack:renderer", 33 | "pack:main": "cross-env NODE_ENV=production webpack --progress --colors --config .electron-vue/webpack.main.config.js", 34 | "pack:renderer": "cross-env NODE_ENV=production webpack --progress --colors --config .electron-vue/webpack.renderer.config.js", 35 | {{#testing unit e2e}} 36 | "test": "{{#unit}}npm run unit{{/unit}}{{#unit}}{{#e2e}} && {{/e2e}}{{/unit}}{{#e2e}}npm run e2e{{/e2e}}", 37 | {{/testing}} 38 | {{#if unit}} 39 | "unit": "karma start test/unit/karma.conf.js", 40 | {{/if}} 41 | "postinstall": "{{#if eslint}}npm run lint:fix{{/if}}" 42 | }, 43 | {{#if_eq builder 'builder'}} 44 | "build": { 45 | "productName": "{{ name }}", 46 | "appId": "{{ appid }}", 47 | "directories": { 48 | "output": "build" 49 | }, 50 | "files": [ 51 | "dist/electron/**/*" 52 | ], 53 | "dmg": { 54 | "contents": [ 55 | { 56 | "x": 410, 57 | "y": 150, 58 | "type": "link", 59 | "path": "/Applications" 60 | }, 61 | { 62 | "x": 130, 63 | "y": 150, 64 | "type": "file" 65 | } 66 | ] 67 | }, 68 | "mac": { 69 | "icon": "build/icons/icon.icns" 70 | }, 71 | "win": { 72 | "icon": "build/icons/icon.ico" 73 | }, 74 | "linux": { 75 | "icon": "build/icons" 76 | } 77 | }, 78 | {{/if_eq}} 79 | "dependencies": { 80 | "vue": "^2.6.12"{{deps plugins}}{{depsf framework}} 81 | }, 82 | "devDependencies": { 83 | "ajv": "^7.0.2", 84 | "@babel/core": "^7.12.10", 85 | "@babel/plugin-syntax-dynamic-import": "^7.8.3", 86 | "@babel/plugin-transform-runtime": "^7.12.10", 87 | "@babel/preset-env": "^7.12.11", 88 | "@babel/preset-react": "^7.12.10", 89 | {{#if_eq framework 'quasar'}} 90 | "@quasar/extras": "^1.9.12", 91 | {{/if_eq}} 92 | "babel-loader": "^8.2.2", 93 | "babel-register": "^6.26.0", 94 | "cfonts": "^2.9.1", 95 | "chalk": "^4.1.0", 96 | "copy-webpack-plugin": "^6.2.1", 97 | "terser-webpack-plugin": "^4.2.3", 98 | "cross-env": "^7.0.3", 99 | "css-loader": "^5.0.1", 100 | "del": "^6.0.0", 101 | "devtron": "^1.4.0", 102 | "electron": "^11.1.1", 103 | "electron-debug": "^3.2.0", 104 | "electron-devtools-installer": "^3.1.1", 105 | {{#if_eq builder 'packager'}} 106 | "electron-packager": "^15.2.0", 107 | "electron-rebuild": "^2.3.4", 108 | {{else}} 109 | "electron-builder": "^22.9.1", 110 | {{/if_eq}} 111 | {{#eslint}} 112 | "babel-eslint": "^10.1.0", 113 | "eslint": "^7.16.0", 114 | "eslint-friendly-formatter": "^4.0.1", 115 | "eslint-loader": "^4.0.2", 116 | "eslint-plugin-html": "^6.1.1", 117 | {{#if_eq eslintConfig 'standard'}} 118 | "eslint-config-standard": "^16.0.2", 119 | "eslint-plugin-import": "^2.22.1", 120 | "eslint-plugin-node": "^11.1.0", 121 | "eslint-plugin-promise": "^4.2.1", 122 | "eslint-plugin-standard": "^5.0.0", 123 | "eslint-plugin-vue": "^7.4.0", 124 | {{/if_eq}} 125 | {{#if_eq eslintConfig 'airbnb'}} 126 | "eslint-config-airbnb-base": "^14.2.1", 127 | "eslint-import-resolver-webpack": "^0.13.0", 128 | "eslint-plugin-import": "^2.22.1", 129 | "eslint-plugin-vue": "^7.4.0", 130 | {{/if_eq}} 131 | {{/eslint}} 132 | "mini-css-extract-plugin": "^1.3.3", 133 | "file-loader": "^6.2.0", 134 | "html-webpack-plugin": "^4.5.0", 135 | {{#if unit}} 136 | "inject-loader": "^4.0.1", 137 | "karma": "^5.2.3", 138 | "karma-chai": "^0.1.0", 139 | "karma-coverage": "^2.0.3", 140 | "karma-electron": "^6.3.1", 141 | "karma-mocha": "^2.0.1", 142 | "karma-sourcemap-loader": "^0.3.8", 143 | "karma-spec-reporter": "^0.0.32", 144 | "karma-webpack": "^4.0.2", 145 | {{/if}} 146 | {{#if e2e}} 147 | "require-dir": "^1.2.0", 148 | "spectron": "^13.0.0", 149 | {{/if}} 150 | {{#testing unit e2e}} 151 | "babel-plugin-istanbul": "^6.0.0", 152 | "chai": "^4.2.0", 153 | "mocha": "^8.2.1", 154 | {{/testing}} 155 | "multispinner": "^0.2.1", 156 | "node-loader": "^1.0.2", 157 | {{#if_eq csspreprocessor 'sass'}} 158 | "node-sass": "^5.0.0", 159 | "sass-loader": "^10.1.0", 160 | {{/if_eq}} 161 | {{#if_eq csspreprocessor 'less'}} 162 | "less": "^4.0.0", 163 | "less-loader": "^7.2.0", 164 | {{/if_eq}} 165 | {{#if_eq csspreprocessor 'stylus'}} 166 | "stylus": "^0.54.8", 167 | "stylus-loader": "^4.3.1", 168 | {{/if_eq}} 169 | "style-loader": "^2.0.0", 170 | "url-loader": "^4.1.1", 171 | "vue-html-loader": "^1.2.4", 172 | "vue-loader": "^15.9.6", 173 | "vue-style-loader": "^4.1.2", 174 | "vue-template-compiler": "^2.6.12", 175 | "webpack": "^4.43.0", 176 | "webpack-cli": "^4.3.0", 177 | "webpack-dev-server": "^3.11.0", 178 | "webpack-hot-middleware": "^2.25.0", 179 | "webpack-merge": "^5.7.3" 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /template/src/index.ejs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{ name }} 6 | <% if (htmlWebpackPlugin.options.nodeModules) { %> 7 | 8 | 11 | <% } %> 12 | 13 | 14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /template/src/main/index.dev.js: -------------------------------------------------------------------------------- 1 | /** 2 | * This file is used specifically and only for development. It installs 3 | * `electron-debug` & `vue-devtools`. There shouldn't be any need to 4 | * modify this file, but it can be used to extend your development 5 | * environment. 6 | */ 7 | 8 | const { app } = require('electron') 9 | 10 | // Install `electron-debug` with `devtron` 11 | require('electron-debug')({ showDevTools: true }) 12 | 13 | // Install `vue-devtools` 14 | app.whenReady().then(() => { 15 | require('devtron').install() 16 | 17 | const installExtension = require('electron-devtools-installer') 18 | installExtension.default(installExtension.VUEJS_DEVTOOLS) 19 | .then(() => {}) 20 | .catch(err => { 21 | console.log('Unable to install `vue-devtools`: \n', err) 22 | }) 23 | }) 24 | 25 | // Require `main` process to boot app 26 | require('./index') 27 | -------------------------------------------------------------------------------- /template/src/main/index.js: -------------------------------------------------------------------------------- 1 | {{#if_eq eslintConfig 'standard'}} 2 | 'use strict' 3 | 4 | {{/if_eq}} 5 | const { app, BrowserWindow } = require('electron') 6 | const { join } = require('path') 7 | 8 | /** 9 | * Set `__static` path to static files in production 10 | * https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-static-assets.html 11 | */ 12 | if (process.env.NODE_ENV !== 'development') { 13 | global.__static = join(__dirname, '/static').replace(/\\/g, '\\\\') 14 | } 15 | 16 | let mainWindow 17 | const winURL = process.env.NODE_ENV === 'development' 18 | ? 'http://localhost:9080' 19 | : join('file://', __dirname, '/index.html') 20 | 21 | function createWindow () { 22 | /** 23 | * Initial window options 24 | */ 25 | mainWindow = new BrowserWindow({ 26 | height: 563, 27 | useContentSize: true, 28 | width: 1000, 29 | webPreferences: { 30 | nodeIntegration: true, 31 | enableRemoteModule: true 32 | } 33 | }) 34 | 35 | mainWindow.loadURL(winURL) 36 | 37 | mainWindow.on('closed', () => { 38 | mainWindow = null 39 | }) 40 | } 41 | 42 | app.whenReady().then(() => { 43 | createWindow() 44 | }) 45 | 46 | app.on('window-all-closed', () => { 47 | if (process.platform !== 'darwin') { 48 | app.quit() 49 | } 50 | }) 51 | 52 | app.on('activate', () => { 53 | if (mainWindow === null) { 54 | createWindow() 55 | } 56 | }) 57 | {{#if_eq builder 'builder'}} 58 | 59 | /** 60 | * Auto Updater 61 | * 62 | * Uncomment the following code below and install `electron-updater` to 63 | * support auto updating. Code Signing with a valid certificate is required. 64 | * https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-electron-builder.html#auto-updating 65 | */ 66 | 67 | /* 68 | import { autoUpdater } from 'electron-updater' 69 | autoUpdater.on('update-downloaded', () => { 70 | autoUpdater.quitAndInstall() 71 | }) 72 | app.on('ready', () => { 73 | if (process.env.NODE_ENV === 'production') autoUpdater.checkForUpdates() 74 | }) 75 | */ 76 | {{/if_eq}} 77 | -------------------------------------------------------------------------------- /template/src/renderer/App.vue: -------------------------------------------------------------------------------- 1 | 10 | 11 | 27 | 28 | 31 | -------------------------------------------------------------------------------- /template/src/renderer/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdydesign/vue-electron/5049ea8407b121176edbbd2e8104e2db319839b7/template/src/renderer/assets/.gitkeep -------------------------------------------------------------------------------- /template/src/renderer/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdydesign/vue-electron/5049ea8407b121176edbbd2e8104e2db319839b7/template/src/renderer/assets/logo.png -------------------------------------------------------------------------------- /template/src/renderer/components/LandingPage.vue: -------------------------------------------------------------------------------- 1 | 31 | 32 | 51 | 52 | 135 | -------------------------------------------------------------------------------- /template/src/renderer/components/LandingPage/SystemInformation.vue: -------------------------------------------------------------------------------- 1 | 46 | 47 | 71 | 72 | 98 | -------------------------------------------------------------------------------- /template/src/renderer/main.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | {{#isEnabled plugins 'axios'}} 3 | import axios from 'axios' 4 | {{/isEnabled}} 5 | 6 | import App from './App' 7 | {{#isEnabled plugins 'vue-router'}} 8 | import router from './router' 9 | {{/isEnabled}} 10 | {{#isEnabled plugins 'vuex'}} 11 | import store from './store' 12 | {{/isEnabled}} 13 | {{#isEnabled framework 'vuetify'}} 14 | import Vuetify from 'vuetify' 15 | import 'vuetify/dist/vuetify.min.css' 16 | 17 | Vue.use(Vuetify) 18 | {{/isEnabled}} 19 | {{#isEnabled framework 'quasar'}} 20 | import Quasar from 'quasar' 21 | 22 | import 'quasar/dist/quasar.min.css' 23 | import '@quasar/extras/material-icons/material-icons.css' 24 | import '@quasar/extras/fontawesome-v5/fontawesome-v5.css' 25 | import '@quasar/extras/mdi-v3/mdi-v3.css' 26 | import '@quasar/extras/ionicons-v4/ionicons-v4.css' 27 | import '@quasar/extras/eva-icons/eva-icons.css' 28 | import '@quasar/extras/themify/themify.css' 29 | import '@quasar/extras/animate/fadeIn.css' 30 | import '@quasar/extras/animate/fadeOut.css' 31 | 32 | Vue.use(Quasar, { 33 | config: { 34 | framework: 'all' 35 | } 36 | }) 37 | {{/isEnabled}} 38 | 39 | {{#isEnabled plugins 'vue-electron'}} 40 | if (!process.env.IS_WEB) Vue.use(require('vue-electron')) 41 | {{/isEnabled}} 42 | {{#isEnabled plugins 'axios'}} 43 | Vue.http = Vue.prototype.$http = axios 44 | {{/isEnabled}} 45 | Vue.config.productionTip = false 46 | 47 | /* eslint-disable no-new */ 48 | new Vue({ 49 | components: { App }, 50 | {{#isEnabled plugins 'vue-router'}} 51 | router, 52 | {{/isEnabled}} 53 | {{#isEnabled plugins 'vuex'}} 54 | store, 55 | {{/isEnabled}} 56 | template: '' 57 | }).$mount('#app') 58 | -------------------------------------------------------------------------------- /template/src/renderer/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | 4 | Vue.use(Router) 5 | 6 | export default new Router({ 7 | routes: [ 8 | { 9 | path: '/', 10 | name: 'landing-page', 11 | component: require('@/components/LandingPage').default 12 | }, 13 | { 14 | path: '*', 15 | redirect: '/' 16 | } 17 | ] 18 | }) 19 | -------------------------------------------------------------------------------- /template/src/renderer/store/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Vuex from 'vuex' 3 | 4 | {{#isEnabled plugins 'vuex-electron'}} 5 | import { createPersistedState, createSharedMutations } from 'vuex-electron' 6 | 7 | {{/isEnabled}} 8 | import modules from './modules' 9 | 10 | Vue.use(Vuex) 11 | 12 | export default new Vuex.Store({ 13 | modules, 14 | {{#isEnabled plugins 'vuex-electron'}} 15 | plugins: [ 16 | createPersistedState(), 17 | createSharedMutations() 18 | ], 19 | {{/isEnabled}} 20 | strict: process.env.NODE_ENV !== 'production' 21 | }) 22 | -------------------------------------------------------------------------------- /template/src/renderer/store/modules/Counter.js: -------------------------------------------------------------------------------- 1 | const state = { 2 | main: 0 3 | } 4 | 5 | const mutations = { 6 | DECREMENT_MAIN_COUNTER (state) { 7 | {{#if_eq eslintConfig 'airbnb'}}state.main = state.main - 1{{else}}state.main--{{/if_eq}} 8 | }, 9 | INCREMENT_MAIN_COUNTER (state) { 10 | {{#if_eq eslintConfig 'airbnb'}}state.main = state.main + 1{{else}}state.main++{{/if_eq}} 11 | } 12 | } 13 | 14 | const actions = { 15 | someAsyncTask ({ commit }) { 16 | // do something async 17 | commit('INCREMENT_MAIN_COUNTER') 18 | } 19 | } 20 | 21 | export default { 22 | state, 23 | mutations, 24 | actions 25 | } 26 | -------------------------------------------------------------------------------- /template/src/renderer/store/modules/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * The file enables `@/store/index.js` to import all vuex modules 3 | * in a one-shot manner. There should not be any reason to edit this file. 4 | */ 5 | 6 | const files = require.context('.', false, /\.js$/) 7 | const modules = {} 8 | 9 | files.keys().forEach(key => { 10 | if (key === './index.js') return 11 | modules[key.replace(/(\.\/|\.js)/g, '')] = files(key).default 12 | }) 13 | 14 | export default modules 15 | -------------------------------------------------------------------------------- /template/static/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kdydesign/vue-electron/5049ea8407b121176edbbd2e8104e2db319839b7/template/static/.gitkeep -------------------------------------------------------------------------------- /template/test/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "mocha": true 4 | }, 5 | "globals": { 6 | "assert": true, 7 | "expect": true, 8 | "should": true, 9 | "__static": true 10 | }{{#if eslint}}{{#if_eq eslintConfig 'airbnb'}}, 11 | "rules": { 12 | "func-names": 0, 13 | "prefer-arrow-callback": 0 14 | }{{/if_eq}}{{/if}} 15 | } 16 | -------------------------------------------------------------------------------- /template/test/e2e/index.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | // Set BABEL_ENV to use proper env config 4 | process.env.BABEL_ENV = 'test' 5 | 6 | // Enable use of ES6+ on required files 7 | require('babel-register')({ 8 | ignore: /node_modules/ 9 | }) 10 | 11 | // Attach Chai APIs to global scope 12 | const { expect, should, assert } = require('chai') 13 | global.expect = expect 14 | global.should = should 15 | global.assert = assert 16 | 17 | // Require all JS files in `./specs` for Mocha to consume 18 | require('require-dir')('./specs') 19 | -------------------------------------------------------------------------------- /template/test/e2e/specs/Launch.spec.js: -------------------------------------------------------------------------------- 1 | import utils from '../utils' 2 | 3 | describe('Launch', function () { 4 | beforeEach(utils.beforeEach) 5 | afterEach(utils.afterEach) 6 | 7 | it('shows the proper application title', function () { 8 | return this.app.client.getTitle() 9 | .then(title => { 10 | expect(title).to.equal('{{ name }}') 11 | }) 12 | }) 13 | }) 14 | -------------------------------------------------------------------------------- /template/test/e2e/utils.js: -------------------------------------------------------------------------------- 1 | import electron from 'electron' 2 | import { Application } from 'spectron' 3 | 4 | export default { 5 | afterEach () { 6 | this.timeout(10000) 7 | 8 | if (this.app && this.app.isRunning()) { 9 | return this.app.stop() 10 | } 11 | }, 12 | beforeEach () { 13 | this.timeout(10000) 14 | this.app = new Application({ 15 | path: electron, 16 | args: ['dist/electron/main.js'], 17 | startTimeout: 10000, 18 | waitTimeout: 10000 19 | }) 20 | 21 | return this.app.start() 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /template/test/unit/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | Vue.config.devtools = false 3 | Vue.config.productionTip = false 4 | 5 | // require all test files (files that ends with .spec.js) 6 | const testsContext = require.context('./specs', true, /\.spec$/) 7 | testsContext.keys().forEach(testsContext) 8 | 9 | // require all src files except main.js for coverage. 10 | // you can also change this to match only the subset of files that 11 | // you want coverage for. 12 | const srcContext = require.context('../../src/renderer', true, /^\.\/(?!main(\.js)?$)/) 13 | srcContext.keys().forEach(srcContext) 14 | -------------------------------------------------------------------------------- /template/test/unit/karma.conf.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const path = require('path') 4 | const merge = require('webpack-merge') 5 | const webpack = require('webpack') 6 | 7 | const baseConfig = require('../../.electron-vue/webpack.renderer.config') 8 | const projectRoot = path.resolve(__dirname, '../../src/renderer') 9 | 10 | // Set BABEL_ENV to use proper preset config 11 | process.env.BABEL_ENV = 'test' 12 | 13 | let webpackConfig = merge(baseConfig, { 14 | devtool: '#inline-source-map', 15 | plugins: [ 16 | new webpack.DefinePlugin({ 17 | 'process.env.NODE_ENV': '"testing"' 18 | }) 19 | ] 20 | }) 21 | 22 | // don't treat dependencies as externals 23 | delete webpackConfig.entry 24 | delete webpackConfig.externals 25 | delete webpackConfig.output.libraryTarget 26 | 27 | // apply vue option to apply isparta-loader on js 28 | webpackConfig.module.rules 29 | .find(rule => rule.use.loader === 'vue-loader').use.options.loaders.js = 'babel-loader' 30 | 31 | module.exports = config => { 32 | config.set({ 33 | browsers: ['visibleElectron'], 34 | client: { 35 | useIframe: false 36 | }, 37 | coverageReporter: { 38 | dir: './coverage', 39 | reporters: [ 40 | { type: 'lcov', subdir: '.' }, 41 | { type: 'text-summary' } 42 | ] 43 | }, 44 | customLaunchers: { 45 | 'visibleElectron': { 46 | base: 'Electron', 47 | flags: ['--show'] 48 | } 49 | }, 50 | frameworks: ['mocha', 'chai'], 51 | files: ['./index.js'], 52 | preprocessors: { 53 | './index.js': ['webpack', 'sourcemap'] 54 | }, 55 | reporters: ['spec', 'coverage'], 56 | singleRun: true, 57 | webpack: webpackConfig, 58 | webpackMiddleware: { 59 | noInfo: true 60 | } 61 | }) 62 | } 63 | -------------------------------------------------------------------------------- /template/test/unit/specs/LandingPage.spec.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import LandingPage from '@/components/LandingPage' 3 | 4 | describe('LandingPage.vue', () => { 5 | it('should render correct contents', () => { 6 | const vm = new Vue({ 7 | el: document.createElement('div'), 8 | render: h => h(LandingPage) 9 | }).$mount() 10 | 11 | expect(vm.$el.querySelector('.title').textContent).to.contain('Welcome to your new project!') 12 | }) 13 | }) 14 | -------------------------------------------------------------------------------- /test/index.test.js: -------------------------------------------------------------------------------- 1 | const data = { 2 | destDirName: 've4', 3 | inPlace: false, 4 | noEscape: true, 5 | name: 've4', 6 | appid: 'com.example.yourapp', 7 | appver: '0.0.1', 8 | description: 'An electron-vue project', 9 | csspreprocessor: 'sass', 10 | plugins: { 11 | axios: true, 12 | 'vue-electron': true, 13 | 'vue-router': true, 14 | vuex: true, 15 | 'vuex-electron': true 16 | }, 17 | framework: 'vuetify', 18 | eslint: true, 19 | eslintConfig: 'standard', 20 | unit: true, 21 | e2e: true, 22 | builder: 'builder', 23 | autoInstall: 'npm', 24 | author: 'kdydesign ' 25 | } 26 | 27 | describe('utils', () => { 28 | test('true', () => { 29 | expect(data).toHaveProperty('destDirName') 30 | }) 31 | }) 32 | -------------------------------------------------------------------------------- /utils/index.js: -------------------------------------------------------------------------------- 1 | const path = require('path') 2 | const fs = require('fs') 3 | const spawn = require('child_process').spawn 4 | 5 | const lintStyles = ['standard', 'airbnb'] 6 | 7 | /** 8 | * Sorts dependencies in package.json alphabetically. 9 | * They are unsorted because they were grouped for the handlebars helpers 10 | * @param {object} data Data from questionnaire 11 | */ 12 | exports.sortDependencies = function sortDependencies (data) { 13 | const packageJsonFile = path.join( 14 | data.inPlace ? '' : data.destDirName, 15 | 'package.json' 16 | ) 17 | const packageJson = JSON.parse(fs.readFileSync(packageJsonFile)) 18 | 19 | packageJson.devDependencies = sortObject(packageJson.devDependencies) 20 | packageJson.dependencies = sortObject(packageJson.dependencies) 21 | 22 | fs.writeFileSync(packageJsonFile, JSON.stringify(packageJson, null, 2) + '\n') 23 | } 24 | 25 | /** 26 | * Runs `npm install` in the project directory 27 | * @param {string} cwd Path of the created project directory 28 | * @param {object} data Data from questionnaire 29 | */ 30 | exports.installDependencies = function installDependencies ( 31 | cwd, 32 | executable = 'npm', 33 | color 34 | ) { 35 | console.log(`\n\n# ${color('Installing project dependencies ...')}`) 36 | console.log('# ========================\n') 37 | 38 | return runCommand(executable, ['install'], { 39 | cwd 40 | }) 41 | } 42 | 43 | /** 44 | * Runs `npm run lint -- --fix` in the project directory 45 | * @param {string} cwd Path of the created project directory 46 | * @param {object} data Data from questionnaire 47 | */ 48 | exports.runLintFix = function runLintFix (cwd, data, color) { 49 | if (data.lint && lintStyles.indexOf(data.lintConfig) !== -1) { 50 | console.log( 51 | `\n\n${color( 52 | 'Running eslint --fix to comply with chosen preset rules...' 53 | )}` 54 | ) 55 | console.log('# ========================\n') 56 | 57 | const args = 58 | data.autoInstall === 'npm' 59 | ? ['run', 'lint', '--', '--fix'] 60 | : ['run', 'lint', '--fix'] 61 | 62 | return runCommand(data.autoInstall, args, { 63 | cwd 64 | }) 65 | } 66 | 67 | return Promise.resolve() 68 | } 69 | 70 | /** 71 | * Prints the final message with instructions of necessary next steps. 72 | * @param {Object} data Data from questionnaire. 73 | */ 74 | exports.printMessage = function printMessage (data, { green, yellow }) { 75 | const message = ` 76 | # ${green('Project initialization finished!')} 77 | # ======================== 78 | To get started: 79 | ${yellow( 80 | `${data.inPlace ? '' : `cd ${data.destDirName}\n `}${installMsg( 81 | data 82 | )}${lintMsg(data)}npm run dev` 83 | )} 84 | 85 | Documentation can be found at https://vuejs-templates.github.io/webpack 86 | ` 87 | console.log(message) 88 | } 89 | 90 | /** 91 | * If the user will have to run lint --fix themselves, it returns a string 92 | * containing the instruction for this step. 93 | * @param {Object} data Data from questionnaire. 94 | */ 95 | function lintMsg (data) { 96 | return !data.autoInstall && 97 | data.lint && 98 | lintStyles.indexOf(data.lintConfig) !== -1 99 | ? 'npm run lint -- --fix (or for yarn: yarn run lint --fix)\n ' 100 | : '' 101 | } 102 | 103 | /** 104 | * If the user will have to run `npm install` or `yarn` themselves, it returns a string 105 | * containing the instruction for this step. 106 | * @param {Object} data Data from the questionnaire 107 | */ 108 | function installMsg (data) { 109 | return !data.autoInstall ? 'npm install (or if using yarn: yarn)\n ' : '' 110 | } 111 | 112 | /** 113 | * Spawns a child process and runs the specified command 114 | * By default, runs in the CWD and inherits stdio 115 | * Options are the same as node's child_process.spawn 116 | * @param {string} cmd 117 | * @param {array} args 118 | * @param {object} options 119 | */ 120 | function runCommand (cmd, args, options) { 121 | return new Promise((resolve, reject) => { 122 | const spwan = spawn( 123 | cmd, 124 | args, 125 | Object.assign( 126 | { 127 | cwd: process.cwd(), 128 | stdio: 'inherit', 129 | shell: true 130 | }, 131 | options 132 | ) 133 | ) 134 | 135 | spwan.on('exit', () => { 136 | resolve() 137 | }) 138 | }) 139 | } 140 | 141 | function sortObject (object) { 142 | // Based on https://github.com/yarnpkg/yarn/blob/v1.3.2/src/config.js#L79-L85 143 | const sortedObject = {} 144 | Object.keys(object) 145 | .sort() 146 | .forEach(item => { 147 | sortedObject[item] = object[item] 148 | }) 149 | return sortedObject 150 | } 151 | --------------------------------------------------------------------------------