Skip to content

Commit 6374621

Browse files
committed
feat: support deal with github-pages
1 parent 629cacc commit 6374621

15 files changed

+336
-189
lines changed

package-lock.json

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "pri",
3-
"version": "0.0.41",
3+
"version": "0.0.42",
44
"types": "src/index.ts",
55
"main": "built/index.js",
66
"scripts": {
@@ -62,6 +62,7 @@
6262
"ora": "^1.4.0",
6363
"parcel-bundler": "^1.6.1",
6464
"portfinder": "^1.0.13",
65+
"pre-commit": "^1.2.2",
6566
"prettier": "^1.10.2",
6667
"react": "^16.2.0",
6768
"react-dom": "^16.2.0",
@@ -76,7 +77,6 @@
7677
"typescript": "^2.7.1",
7778
"update-notifier": "^2.3.0",
7879
"walk": "^2.3.9",
79-
"yargs": "^11.0.0",
80-
"pre-commit": "^1.2.2"
80+
"yargs": "^11.0.0"
8181
}
8282
}

readme.md

+57-4
Original file line numberDiff line numberDiff line change
@@ -159,19 +159,38 @@ Production deployment. By default the dist folder is `./dist`.
159159
**`ProjectConfig` Details**
160160

161161
```typescript
162-
class IConfig {
162+
export class IProjectConfig {
163163
/**
164164
* Title for html <title>
165165
*/
166166
public title?: string = "pri"
167167
/**
168-
* Dist dir path when running: npm run build | pri build
168+
* Dist dir path
169+
* Only take effect on npm run build | pri build
169170
*/
170171
public distDir?: string = "dist"
171172
/**
172-
* Public url path when running: npm run build | pri build
173+
* Assets public path. eg: some.com, some.com/somePath, /somePath
174+
* If not set, result: /<distPath>
175+
* If set /somePath for example, result: /somePath/<distPath>
176+
* If set some.com for example, result: //some.com/<distPath>
177+
* If set some.com/somePath for example, result: //some.com/somePath/<distPath>
178+
* Only take effect on npm run build | pri build
173179
*/
174180
public publicPath?: string | null = null
181+
/**
182+
* Base href for all pages.
183+
* For example, /admin is the root path after deploy, you should set baseHref to /admin.
184+
* There is no need to modify the code, routing / can automatically maps to /admin.
185+
* Only take effect on npm run build | pri build
186+
*/
187+
public baseHref?: string = "/"
188+
/**
189+
* Generate static index file for each route, when building.
190+
* Usefal for static service who don't serve fallback html, like github-pages.
191+
* Only take effect on npm run build | pri build
192+
*/
193+
public staticBuild = false
175194
/**
176195
* Custom env
177196
*/
@@ -289,6 +308,41 @@ Production deployment. By default the dist folder is `./dist`.
289308

290309
</details>
291310

311+
<details>
312+
<summary>Deploy to github pages.</summary>
313+
314+
<p>
315+
316+
Set up `publicPath`, `baseHref` and `staticBuild` in the **Custom config**.
317+
318+
```typescript
319+
// src/config/config.default.ts
320+
321+
import { ProjectConfig } from "pri"
322+
323+
export default {
324+
staticBuild: true,
325+
publicPath: "/<your-repo-name>",
326+
baseHref: "/<your-repo-name>"
327+
} as ProjectConfig
328+
```
329+
330+
Then, execute `npm i gh-pages --save-dev`, and add npm scripts:
331+
332+
```json
333+
"deploy": "pri build && && gh-pages -d dist"
334+
```
335+
336+
Finally, execute `npm run deploy`!
337+
338+
> This is because js files will be served from `/<your-repo-name>` and the root path changed to `/<your-repo-name>` on github-pages.
339+
340+
> `staticBuild` will generate static index file for each route.
341+
342+
</p>
343+
344+
</details>
345+
292346
#### TODO
293347

294348
- Static file serving.
@@ -489,7 +543,6 @@ Production deployment. By default the dist folder is `./dist`.
489543
- Scope Hoist.
490544
- Prefetching.
491545
- Code coverage.
492-
- Static html.
493546

494547
## Inspired
495548

src/bin.ts

+13-10
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { log } from "./utils/log"
1616
/**
1717
* -V --version
1818
*/
19-
commander.version(pkg.version, "-v, --version");
19+
commander.version(pkg.version, "-v, --version")
2020

2121
/**
2222
* Regist commander.
@@ -26,32 +26,35 @@ commander.command(DEV)
2626
.description("Develop your project.")
2727
.action(async () => {
2828
await CommandDev()
29-
});
29+
})
3030

3131
const BUILD = "build"
3232
commander.command(BUILD)
3333
.description("Pack your project.")
34-
.action(async () => {
35-
await CommandBuild()
36-
});
34+
.option("-s, --static")
35+
.action(async (options) => {
36+
await CommandBuild({
37+
static: options.static
38+
})
39+
})
3740

3841
const PREVIEW = "preview"
3942
commander.command(PREVIEW)
4043
.description("Preview your project in production mode.")
4144
.action(async () => {
4245
await CommandPreview()
43-
});
46+
})
4447

4548
const INIT = "init"
4649
commander.command(INIT)
4750
.action(async () => {
4851
await CommandInit()
49-
});
52+
})
5053

5154
/**
5255
* Parse argv.
5356
*/
54-
commander.parse(process.argv);
57+
commander.parse(process.argv)
5558

5659
/**
5760
* When no args given, use dev command
@@ -67,5 +70,5 @@ updateNotifier({ pkg }).notify()
6770

6871
// 捕获异常
6972
process.on("unhandledRejection", error => {
70-
log(colors.red(error.toString()));
71-
});
73+
log(colors.red(error.toString()))
74+
})

src/commands/build/index.ts

+27-73
Original file line numberDiff line numberDiff line change
@@ -2,103 +2,57 @@ import { execSync } from "child_process"
22
import * as colors from "colors"
33
import * as fs from "fs-extra"
44
import * as path from "path"
5-
import { Configuration, Linter } from "tslint"
65
import { analyseProject } from "../../utils/analyse-project"
76
import { createEntry } from "../../utils/create-entry"
87
import { ensureFiles } from "../../utils/ensure-files"
8+
import { generateHtmlByRouterPath, generateStaticHtml } from "../../utils/generate-static-html"
99
import { log, spinner } from "../../utils/log"
1010
import { findNearestNodemodules } from "../../utils/npm-finder"
1111
import { getConfig } from "../../utils/project-config"
12-
import { IConfig } from "../../utils/project-config-interface"
12+
import { IProjectConfig } from "../../utils/project-config-interface"
13+
import { lint } from "../../utils/tslint"
1314

1415
const projectRootPath = process.cwd();
1516

16-
export const CommandBuild = async () => {
17+
export const CommandBuild = async (options: {
18+
static?: boolean
19+
}) => {
1720
const env = "prod"
18-
const config = getConfig(projectRootPath, env)
21+
const projectConfig = getConfig(projectRootPath, env)
1922

2023
// tslint check
21-
log("Pre-commit checks...")
24+
lint(projectRootPath)
2225

23-
const configurationFilename = "tslint.json"
24-
const options = {
25-
fix: true,
26-
formatter: "json"
27-
}
28-
29-
const program = Linter.createProgram("tsconfig.json", projectRootPath)
30-
const linter = new Linter(options, program)
31-
32-
const files = Linter.getFileNames(program)
33-
files.forEach(file => {
34-
const fileContents = program.getSourceFile(file).getFullText()
35-
const configuration = Configuration.findConfiguration(configurationFilename, file).results
36-
linter.lint(file, fileContents, configuration)
37-
})
38-
39-
const results = linter.getResult()
26+
// Clean dist dir
27+
execSync(`rm -rf ${path.join(projectRootPath, projectConfig.distDir)}`)
4028

41-
if (results.errorCount > 0) {
42-
log(colors.red(`Tslint errors:`))
43-
results.failures.forEach(failure => {
44-
const errorPosition = failure.getStartPosition().getLineAndCharacter()
45-
log(colors.red(`${failure.getFailure()}`), ", at: ", `${failure.getFileName()}:${errorPosition.line}:${errorPosition.character}`)
46-
})
47-
process.exit(0)
48-
}
49-
50-
if (results.fixes.length > 0) {
51-
log(`Tslint auto fixed ${results.fixes.length} bugs`)
52-
}
29+
// Clean .temp dir
30+
execSync(`rm -rf ${path.join(projectRootPath, ".temp")}`)
5331

5432
await spinner("Ensure project files", async () => {
55-
ensureFiles(projectRootPath, config)
33+
ensureFiles(projectRootPath, projectConfig)
5634
})
5735

58-
const entryPath = await spinner("Analyse project", async () => {
59-
const info = await analyseProject(projectRootPath)
60-
return createEntry(info, projectRootPath, env, config)
36+
const result = await spinner("Analyse project", async () => {
37+
const projectInfo = await analyseProject(projectRootPath)
38+
const entryPath = await createEntry(projectInfo, projectRootPath, env, projectConfig)
39+
return {
40+
projectInfo, entryPath
41+
}
6142
})
6243

63-
let publicUrl = ""
64-
if (config.publicPath) {
65-
publicUrl = `--public-url ${config.publicPath}`
44+
// If using staticBuild, generate index pages for all router.
45+
if (projectConfig.staticBuild) {
46+
await spinner("Generate static files.", async () => {
47+
await generateStaticHtml(projectRootPath, projectConfig, result.projectInfo)
48+
})
6649
}
6750

6851
// Run parcel
69-
execSync(`${findNearestNodemodules()}/.bin/parcel build ${entryPath} --out-dir ${path.join(projectRootPath, config.distDir || "dist")} ${publicUrl}`, {
52+
execSync(`${findNearestNodemodules()}/.bin/parcel build ${result.entryPath} --out-dir ${path.join(projectRootPath, projectConfig.distDir || "dist")}`, {
7053
stdio: "inherit",
7154
cwd: __dirname
72-
});
73-
74-
createEntryHtmlFile("/entry.js", config)
75-
}
76-
77-
function createEntryHtmlFile(entryPath: string, config: IConfig) {
78-
const htmlPath = path.join(projectRootPath, "dist/index.html")
79-
80-
fs.outputFileSync(htmlPath, `
81-
<html>
82-
83-
<head>
84-
<title>${config.title}</title>
85-
86-
<style>
87-
html,
88-
body {
89-
margin: 0;
90-
padding: 0;
91-
}
92-
</style>
93-
</head>
94-
95-
<body>
96-
<div id="root"></div>
97-
<script src="${entryPath}"></script>
98-
</body>
99-
100-
</html>
101-
`)
55+
})
10256

103-
return htmlPath
57+
generateHtmlByRouterPath("/", projectRootPath, projectConfig)
10458
}
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { IProjectInfo } from "../../../../utils/analyse-project-interface"
2-
import { IConfig } from "../../../../utils/project-config-interface"
2+
import { IProjectConfig } from "../../../../utils/project-config-interface"
33

44
export interface IProjectStatus {
5-
config: IConfig
5+
config: IProjectConfig
66
info: IProjectInfo
77
}

src/commands/dev/index.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { ensureFiles } from "../../utils/ensure-files"
99
import { log, spinner } from "../../utils/log"
1010
import { findNearestNodemodules } from "../../utils/npm-finder"
1111
import { getConfig } from "../../utils/project-config"
12-
import { IConfig } from "../../utils/project-config-interface"
12+
import { IProjectConfig } from "../../utils/project-config-interface"
1313

1414
const projectRootPath = process.cwd();
1515

@@ -76,7 +76,7 @@ export const CommandDev = async () => {
7676
}
7777
}
7878

79-
function createEntryHtmlFile(entryPath: string, config: IConfig, dashboardServerPort: number) {
79+
function createEntryHtmlFile(entryPath: string, config: IProjectConfig, dashboardServerPort: number) {
8080
const htmlPath = path.join(projectRootPath, ".temp/dev.html")
8181

8282
fs.outputFileSync(htmlPath, `

0 commit comments

Comments
 (0)