├── .gitignore ├── logo.png ├── screenshot.gif ├── src ├── hack │ ├── README.md │ └── hack.json ├── bin │ └── vue-cli-ghpages └── index.js ├── LICENSE ├── package.json └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | .vscode 4 | npm-debug.log 5 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeneser/vue-cli-ghpages/HEAD/logo.png -------------------------------------------------------------------------------- /screenshot.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeneser/vue-cli-ghpages/HEAD/screenshot.gif -------------------------------------------------------------------------------- /src/hack/README.md: -------------------------------------------------------------------------------- 1 | # Hack 2 | 3 | > The Single Page App Hack for GitHub Pages 4 | 5 | ## hack.json 6 | 7 | Instructions: 8 | 9 | - **name** - hack.json 10 | - **version** - Version 11 | - **description** - Description 12 | - **nojekyll** - Turns off Jekyll for GitHub Pages 13 | - **CNAME** - Setting up a custom domain 14 | - **notFoundHtml** - The custom 404.html page contains a script that takes the current url and converts the path and query string into just a query string,and then redirects the browser to the new url with only a query string and hash fragment. 15 | - **indexRedirect** - This script checks to see if a redirect is present in the query string and converts it back into the correct url and adds it to the browser's history using window.history.replaceState(...) 16 | 17 | Learn more: https://github.com/rafrex/spa-github-pages 18 | 19 | ## License 20 | 21 | MIT Copyright (c) 2017 [Jeneser](https://github.com/jeneser) 22 | 23 | MIT Copyright (c) 2016 [Rafael Pedicini](https://github.com/rafrex) 24 | -------------------------------------------------------------------------------- /src/hack/hack.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "hack.json", 3 | "version": "1.0.0", 4 | "description": "Single Page Apps Hack for GitHub Pages", 5 | "nojekyll": ".nojekyll", 6 | "CNAME": "", 7 | "notFoundHtml": "Single Page Apps for GitHub Pages", 8 | "indexRedirect": "" 9 | } -------------------------------------------------------------------------------- /src/bin/vue-cli-ghpages: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var pjson = require('../../package.json'); 4 | var index = require('../index.js'); 5 | var program = require('commander'); 6 | 7 | program 8 | .version(pjson.version) 9 | .description(pjson.description) 10 | .option('-d, --dir ', 'The directory you will deploy, relative to the project-root', 'dist') 11 | .option('-m, --message ', 'The commit message, must be wrapped in quotes', 'Vcg: Update live demo') 12 | .option('-b, --branch ', 'The git branch to push your live demo', 'gh-pages') 13 | .option('-n, --name ', 'The git user-name which is associated with this commit') 14 | .option('-e, --email ', 'The git user-email which is associated with this commit') 15 | .option('-r, --repo ', 'The repository URL, if the current working directory is not a git repository. must be wrapped in quotes.') 16 | .option('-C, --CNAME ', 'Setting up a custom domain, Like: demo.example.com') 17 | .parse(process.argv); 18 | 19 | index.run(program) 20 | .catch(error => process.exit(1)); 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 yazhe wang 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 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue-cli-ghpages", 3 | "version": "1.0.0", 4 | "description": "GitHub pages for vue-cli users. Publish to gh-pages branch on GitHub. The Single-Page App Hack for GitHub Pages.", 5 | "files": [ 6 | "src" 7 | ], 8 | "main": "src/index.js", 9 | "bin": { 10 | "vue-cli-ghpages": "src/bin/vue-cli-ghpages", 11 | "vcg": "src/bin/vue-cli-ghpages" 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "git+https://github.com/jeneser/vue-cli-ghpages.git" 16 | }, 17 | "bugs": { 18 | "url": "https://github.com/jeneser/vue-cli-ghpages/issues" 19 | }, 20 | "author": { 21 | "name": "jeneser", 22 | "email": "jeneserwang@gmail.com" 23 | }, 24 | "license": "MIT", 25 | "dependencies": { 26 | "commander": "^2.11.0", 27 | "denodeify": "^1.2.1", 28 | "fs-extra": "^4.0.1", 29 | "gh-pages": "^1.0.0", 30 | "ora": "^1.3.0" 31 | }, 32 | "keywords": [ 33 | "vue", 34 | "vue.js", 35 | "vue-cli", 36 | "vue2", 37 | "git", 38 | "github pages", 39 | "gh-pages", 40 | "ghpages", 41 | "vue-cli-ghpages", 42 | "vue-cli-github-pages" 43 | ] 44 | } 45 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var fs = require('fs'); 3 | var fse = require('fs-extra'); 4 | var ora = require('ora'); 5 | var ghpages = require('gh-pages'); 6 | var denodeify = require('denodeify'); 7 | var hjson = require('./hack/hack.json'); 8 | 9 | exports.run = function(options) { 10 | options = options || {}; 11 | 12 | var access = denodeify(fs.access); 13 | var readFile = denodeify(fs.readFile); 14 | var publish = denodeify(ghpages.publish); 15 | 16 | var ensureFile = fse.ensureFile; 17 | var outputFile = fse.outputFile; 18 | 19 | const spinner = ora('Start deployment...').start(); 20 | 21 | var dir = path.join(process.cwd(), options.dir); 22 | 23 | if (options.name && options.email) { 24 | options.user = { 25 | name: options.name, 26 | email: options.email 27 | }; 28 | } 29 | 30 | // clean the cache directory 31 | ghpages.clean(); 32 | 33 | return ( 34 | Promise.resolve() 35 | /** 36 | * Tests user's permissions for the directory 37 | */ 38 | .then(() => access(dir, fs.constants.F_OK)) 39 | .catch(error => { 40 | spinner.fail( 41 | 'Dist folder does not exist. Check the dir --dir parameter or build the project first!' 42 | ); 43 | return Promise.reject(error); 44 | }) 45 | /** 46 | * Create .nojekyll 47 | */ 48 | .then(() => ensureFile(path.join(dir, '.nojekyll'))) 49 | .catch(error => 50 | spinner.warn( 51 | '.nojekyll could not be created. Please create manually. Continuing without an error.' 52 | ) 53 | ) 54 | /** 55 | * Setting up custom domain 56 | */ 57 | .then(() => ensureFile(path.join(dir, 'CNAME'))) 58 | .then(() => readFile(path.join(dir, 'CNAME'), 'utf8')) 59 | .then(data => 60 | outputFile( 61 | path.join(dir, 'CNAME'), 62 | options.CNAME ? options.CNAME : data.replace(/\s+/, '') 63 | ) 64 | ) 65 | .catch(() => 66 | spinner.warn( 67 | 'CNAME could not be created. Please create manually. Continuing without an error.' 68 | ) 69 | ) 70 | /** 71 | * Output 404.html, setting segmentCount 72 | */ 73 | .then(() => readFile(path.join(dir, 'CNAME'), 'utf8')) 74 | .then(data => 75 | outputFile( 76 | path.join(dir, '404.html'), 77 | data 78 | ? hjson.notFoundHtml.replace( 79 | /segmentCount\s=\s1/, 80 | 'segmentCount = 0' 81 | ) 82 | : hjson.notFoundHtml 83 | ) 84 | ) 85 | .catch(error => { 86 | spinner.fail( 87 | '404.html could not be created. An error occurred:\n' + error 88 | ); 89 | return Promise.reject(error); 90 | }) 91 | /** 92 | * Inject redirect code to index.html 93 | */ 94 | .then(() => readFile(path.join(dir, 'index.html'), 'utf8')) 95 | .then(data => 96 | outputFile( 97 | path.join(dir, 'index.html'), 98 | data.includes('indexRedirect') 99 | ? data 100 | : data.replace(//, '' + hjson.indexRedirect) 101 | ) 102 | ) 103 | .catch(error => { 104 | spinner.fail( 105 | 'Unable to inject redirection code to index.html. Error occurred:\n' + 106 | error 107 | ); 108 | return Promise.reject(error); 109 | }) 110 | /** 111 | * Publish via ghpages 112 | */ 113 | .then(() => { 114 | spinner.text = 'Deploying, please wait a moment...'; 115 | return publish(dir, options); 116 | }) 117 | // Success 118 | .then(() => { 119 | spinner.succeed('Successfully deployed!'); 120 | }) 121 | .catch(error => { 122 | spinner.fail('Error occurred:\n' + error); 123 | return Promise.reject(error); 124 | }) 125 | ); 126 | }; 127 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **DANGER: Hack code bug, wontfix!** 2 | 3 |

4 | logo 5 |

6 | 7 | ## vue-cli-ghpages 8 | 9 | [![npm version](https://badge.fury.io/js/vue-cli-ghpages.svg)](https://badge.fury.io/js/vue-cli-ghpages) [![David](https://img.shields.io/david/expressjs/express.svg?style=flat-square)](https://github.com/jeneser/vue-cli-ghpages) [![Percentage of issues still open](http://isitmaintained.com/badge/open/jeneser/vue-cli-ghpages.svg)](http://isitmaintained.com/project/jeneser/vue-cli-ghpages "Percentage of issues still open") [![PR](https://img.shields.io/badge/PR-welcome-brightgreen.svg)](https://github.com/jeneser/vue-cli-ghpages/pulls) [![license](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://github.com/jeneser) 10 | 11 | [![NPM](https://nodei.co/npm/vue-cli-ghpages.png?downloads=true&downloadRank=true&stars=true)](https://nodei.co/npm/vue-cli-ghpages/) 12 | 13 | Publish to any `gh-pages` branch on GitHub. The Single-Page App [**Hack**](https://github.com/jeneser/vue-cli-ghpages/tree/master/src/hack) for GitHub Pages. 14 | 15 | A clean way of deploying vue-cli apps to [`github pages`](https://pages.github.com/). 16 | 17 | Made for [`vue-cli`](https://github.com/vuejs/vue-cli) users. 18 | 19 | Made on top of [tschaub/gh-pages](https://github.com/tschaub/gh-pages). 20 | 21 | Inspired by [`angular-cli-ghpages`](https://github.com/angular-buch/angular-cli-ghpages) and [`spa-github-pages`](https://github.com/rafrex/spa-github-pages). 22 | 23 | 24 | ## Quick start 25 | 26 | Quickly understand what `vue-cli-ghpages` has done. 27 | 28 |

29 | preview 30 |

31 | 32 | ## Installation 33 | 34 | This command has the following prerequisites: 35 | 36 | - Node.js 6.x 37 | - Git 1.7.6 or higher 38 | - **optional:** Vue project created via [vue-cli](https://github.com/vuejs/vue-cli) 39 | 40 | To install the command once globally run the following: 41 | 42 | ``` 43 | $ npm install -g vue-cli-ghpages 44 | ``` 45 | 46 | ## Usage 47 | 48 | Execute `vue-cli-ghpages` in order to deploy the project with a build from `dist` folder. 49 | 50 | **Note: you have to create the dist folder in before (e.g. npm run build)** 51 | 52 | Usage: 53 | 54 | ``` 55 | $ npm run build 56 | $ vue-cli-ghpages [OPTIONS] 57 | ``` 58 | 59 | there is also a shorter `vcg` command available 60 | 61 | ``` 62 | $ npm run build 63 | $ vcg [OPTIONS] 64 | ``` 65 | 66 | **Tip:** If you want to push to `gh-pages` on the same repository with your **default credentials**, then just enter **`vcg`** without any options. 67 | 68 | ## Options 69 | 70 | #### --help 71 | 72 | * Example: `vcg --help` 73 | 74 | Output usage information. 75 | 76 | #### --version 77 | 78 | * Example: `vcg --version` 79 | 80 | Output the version number. 81 | 82 | #### --message 83 | 84 | * **[optional]** 85 | * Default: `Vcg: Update live demo` 86 | * Example: `vcg --message="Update live demo"` 87 | 88 | The commit message, **must be wrapped in quotes**. 89 | 90 | #### --branch 91 | 92 | * **[optional]** 93 | * Default: `gh-pages` 94 | * Example: `vcg --branch=other-branch` 95 | 96 | The name of the branch you'll be pushing to. 97 | The default uses GitHub's `gh-pages` branch, 98 | but this can be configured to push to any branch on any remote. 99 | 100 | #### --name & --email 101 | 102 | * **[optional]** 103 | * Default: value of `git config user.name` and `git config user.email` 104 | * Example: `vcg --name="Displayed Username" --email=mail@example.org` 105 | 106 | If you are running the command in a repository without a `user.name` or `user.email` git config properties 107 | (or on a machine **without** these global config properties), 108 | you **must** provide user info before git allows you to commit. 109 | In this case provide both `name` and `email` string values to identify the committer. 110 | 111 | #### --repo 112 | 113 | * **[optional]** 114 | * Default: url of the origin remote of the current dir (assumes a git repository) 115 | * Example: `vcg --repo=https://example.com/other/repo.git` 116 | 117 | By default, [**gh-pages**](https://github.com/tschaub/gh-pages) assumes that the current working directory is a git repository, 118 | and that you want to push changes to the `origin` remote. 119 | If instead your files are not in a git repository, or if you want to push to another repository, 120 | you can provide the repository URL in the `repo` option. 121 | 122 | #### --dir 123 | 124 | * **[optional]** 125 | * Default: `dist` 126 | 127 | Directory for all published sources, relative to the project-root. 128 | Most probably no change is required here. 129 | This option can be used to deploy completely different folders, 130 | which are not related at all to Vue. 131 | 132 | #### --CNAME 133 | 134 | * **[optional]** 135 | * Default: '' 136 | * Example: `vcg --CNAME=example.io` 137 | 138 | Set up a custom domain. 139 | see GitHub Pages instructions for [setting up a custom domain](https://help.github.com/articles/quick-start-setting-up-a-custom-domain/). 140 | 141 | #### --pre-deploy* 142 | * **[optional]** 143 | * Default: `undefined` 144 | * Example: `vcg --pre-deploy` 145 | 146 | **Take care** the flag. Upcoming... 147 | `*` Check the environment and configuration. Run through without publishing. 148 | 149 | ## Why vue-cli-ghpages? 150 | 151 | **If you’re getting started** with Vue, use `vue-cli` to scaffolding Vue.js projects. **Then, host** `Vue app`(single page apps) with [`github pages`](https://pages.github.com/). 152 | 153 | * You don’t need to install or configure tools like [`gh-pages`](https://github.com/tschaub/gh-pages). 154 | 155 | * You don’t need to waste time Hacking for GitHub Pages. 156 | 157 | * You don’t even need to learning git. 158 | 159 | They are preconfigured and hidden so that you can focus on your code. 160 | 161 | *Just run `vcg`, and you’re good to go.* 162 | 163 | >Why it's necessary? 164 | > 165 | >GitHub Pages doesn't natively support single page apps. When there is a fresh page load for a url like example.tld/foo, where /foo is a frontend route, the GitHub Pages server returns 404 because it knows nothing of /foo. we need Hacking for GitHub Pages. 166 | 167 | *Learn more:* 168 | 169 | [My hack.json](https://github.com/jeneser/vue-cli-ghpages/tree/master/src/hack) | [How it works?](https://github.com/rafrex/spa-github-pages#how-it-works) | [Usage instructions](https://github.com/rafrex/spa-github-pages#usage-instructions) | [Publish files to a gh-pages branch on GitHub](https://github.com/tschaub/gh-pages) 170 | 171 | ## FAQ 172 | 173 |
174 | Why file path is broken and shows blank page on Github Pages?
175 | After publish to gh-pages branch on GitHub. There is still nothing being displayed. File path is broken and shows blank page on Github Pages. Here are the console errors like: Get https://user.github.io/static/[css]|[js]/app.[hash].[css]|[js] 404 (Not Found)
176 | To fix it simplely:
177 | Open up /config/index.js, and find the following line.
178 | assetsPublicPath: '/'
179 | Just change the absolute path to a relative path.
180 | Modify to assetsPublicPath: './' OR assetsPublicPath: 'https://[user].github.io/[project-name]/' 181 |
182 |
183 | Can i use Vue-router HTML5 History Mode?
184 | Beautiful, you can do it.
185 | Since our app is a single page client side app, without a proper server configuration, the users will get a 404 error if they access http://oursite.com/user/id directly in their browser. Now that's ugly.
186 | vue-cli-ghpages fixed the issue preconfigured and hidden. We hacked(catch-all fallback route to your server) it.
187 | If the URL doesn't match any static assets, it should serve the same index.html page that your app lives in. Beautiful, again!
188 | Learn more: How-it-works? https://github.com/rafrex/spa-github-pages#how-it-works 189 |
190 |
191 | Where can I see my deployed github pages url?
192 | Go to you repository settings, scroll down to the GitHub Pages section.
193 | You will see: Your site is published at https://user.github.io/project/
194 |
195 |
196 | My CNAME file is deleted on every publish?
197 | That's by design, the command overrides everything. But, you just need to configure it once. It will make changes based on the existing configuration(CNAME) and flag(--CNAME).
198 | You can also manually modify. (echo "my-domain.com" > dist/CNAME)
199 |
200 | 201 | ## Contributing 202 | 203 | 1. Fork it! 204 | 2. Create your feature branch: `git checkout -b my-new-feature` 205 | 3. Commit your changes: `git commit -am 'Add some feature'` 206 | 4. Push to the branch: `git push origin my-new-feature` 207 | 5. Submit a pull request 208 | 209 | ## Thanks 210 | 211 | [`angular-cli-ghpages`](https://github.com/angular-buch/angular-cli-ghpages) 212 | 213 | [`spa-github-pages`](https://github.com/rafrex/spa-github-pages) 214 | 215 | [`gh-pages`](https://github.com/tschaub/gh-pages) 216 | 217 | ## License 218 | 219 | [MIT](https://github.com/jeneser/vue-cli-ghpages/blob/master/LICENSE) Copyright (c) 2017 [Jeneser](https://jeneser.github.io/) 220 | --------------------------------------------------------------------------------