├── .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 |
5 |
6 |
7 | ## vue-cli-ghpages
8 |
9 | [](https://badge.fury.io/js/vue-cli-ghpages) [](https://github.com/jeneser/vue-cli-ghpages) [](http://isitmaintained.com/project/jeneser/vue-cli-ghpages "Percentage of issues still open") [](https://github.com/jeneser/vue-cli-ghpages/pulls) [](https://github.com/jeneser)
10 |
11 | [](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 |
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 |
--------------------------------------------------------------------------------