@wang1212/create-web-app
Advanced tools
Comparing version 0.3.2 to 0.3.11
@@ -9,19 +9,21 @@ #!/usr/bin/env node | ||
'use strict'; | ||
'use strict' | ||
const chalk = require('chalk'), | ||
fse = require('fs-extra'), | ||
path = require('path'); | ||
fse = require('fs-extra'), | ||
path = require('path') | ||
const app = path.resolve(__dirname, '../packages/react-app/'), | ||
shared = path.resolve(__dirname, '../packages/shared/'), | ||
args = process.argv.slice(2), | ||
project_name = args[0] == null ? 'react-web-app' : args[0]; | ||
project_name = args[0] == null ? 'react-web-app' : args[0] | ||
function error_exit () { | ||
fse.removeSync(path.resolve(process.cwd(), project_name)); | ||
process.exit(); | ||
function error_exit() { | ||
fse.removeSync(path.resolve(process.cwd(), project_name)) | ||
process.exit() | ||
} | ||
function filter_file (src, dest) { | ||
return !src.match(/\.gitkeep$/); | ||
function filter_file(src, dest) { | ||
// ! /node_modules/ - only use local test | ||
return !src.match(/(\.gitkeep$)|build/) | ||
} | ||
@@ -31,48 +33,47 @@ | ||
console.log(`\n Current working directory: ${chalk.cyan(process.cwd())} \n`); | ||
console.log(`\n Current working directory: ${chalk.cyan(process.cwd())} \n`) | ||
console.log(chalk.blue('> Create web app starting...\n')); | ||
console.log(chalk.blue('> Create web app starting...\n')) | ||
if (args[0] == null) { | ||
console.log(`${chalk.red(' Note:')} The project name is not explicitly specified, default is ${chalk.cyan(project_name)}. \n`); | ||
console.log(`${chalk.red(' Note:')} The project name is not explicitly specified, default is ${chalk.cyan(project_name)}. \n`) | ||
} else { | ||
console.log(` The specified project name is ${chalk.cyan(project_name)}. \n`); | ||
console.log(` The specified project name is ${chalk.cyan(project_name)}. \n`) | ||
} | ||
/** | ||
* - Step: Create project dir | ||
*/ | ||
console.log(chalk.blue(`> Step: Create the project directory... \n`)); | ||
console.log(chalk.blue(`> Step: Create the project directory... \n`)) | ||
try { | ||
fse.mkdirSync(project_name); | ||
fse.mkdirSync(project_name) | ||
} catch (err) { | ||
console.error(chalk.red(err.message)); | ||
process.exit(); | ||
console.error(chalk.red(err.message)) | ||
process.exit() | ||
} | ||
console.log(`${chalk.green(' Successful,')} project directory ${chalk.cyan(project_name)} has been created. \n`); | ||
console.log(`${chalk.green(' Successful,')} project directory ${chalk.cyan(project_name)} has been created. \n`) | ||
/** | ||
* - Step: Build project dir structure | ||
*/ | ||
console.log(chalk.blue(`> Step: Build project directory structure and configuration files... \n`)); | ||
console.log(chalk.blue(`> Step: Build project directory structure and configuration files... \n`)) | ||
try { | ||
fse.copySync(app, project_name, { filter: filter_file }); | ||
fse.copySync(app, project_name, { filter: filter_file }) | ||
fse.copySync(path.join(shared, '.gitignore.txt'), path.join(project_name, '.gitignore')) | ||
// update package name with project name | ||
let file_str = fse.readFileSync(path.resolve(process.cwd(), project_name, 'package.json'), 'utf8'); | ||
let file_str = fse.readFileSync(path.resolve(process.cwd(), project_name, 'package.json'), 'utf8') | ||
file_str = file_str.replace(/"name"\s*:\s*"web-app-with-react"\s*,/, `"name": "${project_name}",`); | ||
file_str = file_str.replace(/"name"\s*:\s*"web-app-with-react"\s*,/, `"name": "${project_name}",`) | ||
fse.writeFileSync(path.resolve(process.cwd(), project_name, 'package.json'), file_str); | ||
fse.writeFileSync(path.resolve(process.cwd(), project_name, 'package.json'), file_str) | ||
} catch (err) { | ||
console.error(chalk.red(err.message)); | ||
error_exit(); | ||
console.error(chalk.red(err.message)) | ||
error_exit() | ||
} | ||
console.log(`${chalk.green(' Successful,')} project directory structure and configuration files are ready. \n`); | ||
console.log(`${chalk.green(' Successful,')} project directory structure and configuration files are ready. \n`) | ||
@@ -82,6 +83,6 @@ /** | ||
*/ | ||
console.log(chalk.blue('> Step: Everything is ready. \n')); | ||
console.log(chalk.blue('> Step: Everything is ready. \n')) | ||
console.log(` For more information, read the ${chalk.cyan('README.md')} file in your project directory. \n`); | ||
console.log(` For more information, read the ${chalk.cyan('README.md')} file in your project directory. \n`) | ||
console.log(chalk.green(' Now, start developing your PWA with React.js! Haha...')); | ||
console.log(chalk.green(' Now, start developing your PWA with React.js! Haha...')) |
@@ -9,30 +9,32 @@ #!/usr/bin/env node | ||
'use strict'; | ||
'use strict' | ||
const chalk = require('chalk'), | ||
fse = require('fs-extra'), | ||
path = require('path'); | ||
fse = require('fs-extra'), | ||
path = require('path') | ||
const app = path.resolve(__dirname, '../packages/app/'), | ||
shared = path.resolve(__dirname, '../packages/shared/'), | ||
args = process.argv.slice(2), | ||
project_name = args[0] == null ? 'web-app' : args[0]; | ||
project_name = args[0] == null ? 'web-app' : args[0] | ||
function error_exit () { | ||
fse.removeSync(path.resolve(process.cwd(), project_name)); | ||
process.exit(); | ||
function error_exit() { | ||
fse.removeSync(path.resolve(process.cwd(), project_name)) | ||
process.exit() | ||
} | ||
function filter_file (src, dest) { | ||
return !src.match(/\.gitkeep$/); | ||
function filter_file(src, dest) { | ||
// ! /node_modules/ - only use local test | ||
return !src.match(/(\.gitkeep$)|build/) | ||
} | ||
// start | ||
console.log(`\n Current working directory: ${chalk.cyan(process.cwd())} \n`); | ||
console.log(`\n Current working directory: ${chalk.cyan(process.cwd())} \n`) | ||
console.log(chalk.blue('> Create web app starting...\n')); | ||
console.log(chalk.blue('> Create web app starting...\n')) | ||
if (args[0] == null) { | ||
console.log(`${chalk.red(' Note:')} The project name is not explicitly specified, default is ${chalk.cyan(project_name)}. \n`); | ||
console.log(`${chalk.red(' Note:')} The project name is not explicitly specified, default is ${chalk.cyan(project_name)}. \n`) | ||
} else { | ||
console.log(` The specified project name is ${chalk.cyan(project_name)}. \n`); | ||
console.log(` The specified project name is ${chalk.cyan(project_name)}. \n`) | ||
} | ||
@@ -43,34 +45,34 @@ | ||
*/ | ||
console.log(chalk.blue(`> Step: Create the project directory... \n`)); | ||
console.log(chalk.blue(`> Step: Create the project directory... \n`)) | ||
try { | ||
fse.mkdirSync(project_name); | ||
fse.mkdirSync(project_name) | ||
} catch (err) { | ||
console.error(chalk.red(err.message)); | ||
process.exit(); | ||
console.error(chalk.red(err.message)) | ||
process.exit() | ||
} | ||
console.log(`${chalk.green(' Successful,')} project directory ${chalk.cyan(project_name)} has been created. \n`); | ||
console.log(`${chalk.green(' Successful,')} project directory ${chalk.cyan(project_name)} has been created. \n`) | ||
/** | ||
* - Step: Build project dir structure | ||
*/ | ||
console.log(chalk.blue(`> Step: Build project directory structure and configuration files... \n`)); | ||
console.log(chalk.blue(`> Step: Build project directory structure and configuration files... \n`)) | ||
try { | ||
fse.copySync(app, project_name, { filter: filter_file }); | ||
fse.copySync(app, project_name, { filter: filter_file }) | ||
fse.copySync(path.join(shared, '.gitignore.txt'), path.join(project_name, '.gitignore')) | ||
// update package name with project name | ||
let file_str = fse.readFileSync(path.resolve(process.cwd(), project_name, 'package.json'), 'utf8'); | ||
let file_str = fse.readFileSync(path.resolve(process.cwd(), project_name, 'package.json'), 'utf8') | ||
file_str = file_str.replace(/"name"\s*:\s*"web-app"\s*,/, `"name": "${project_name}",`); | ||
file_str = file_str.replace(/"name"\s*:\s*"web-app"\s*,/, `"name": "${project_name}",`) | ||
fse.writeFileSync(path.resolve(process.cwd(), project_name, 'package.json'), file_str); | ||
fse.writeFileSync(path.resolve(process.cwd(), project_name, 'package.json'), file_str) | ||
} catch (err) { | ||
console.error(chalk.red(err.message)); | ||
error_exit(); | ||
console.error(chalk.red(err.message)) | ||
error_exit() | ||
} | ||
console.log(`${chalk.green(' Successful,')} project directory structure and configuration files are ready. \n`); | ||
console.log(`${chalk.green(' Successful,')} project directory structure and configuration files are ready. \n`) | ||
@@ -80,6 +82,6 @@ /** | ||
*/ | ||
console.log(chalk.blue('> Step: Everything is ready. \n')); | ||
console.log(chalk.blue('> Step: Everything is ready. \n')) | ||
console.log(` For more information, read the ${chalk.cyan('README.md')} file in your project directory. \n`); | ||
console.log(` For more information, read the ${chalk.cyan('README.md')} file in your project directory. \n`) | ||
console.log(chalk.green(' Now, start developing your PWA! Haha...')); | ||
console.log(chalk.green(' Now, start developing your PWA! Haha...')) |
@@ -0,0 +0,0 @@ #!/usr/bin/env node |
@@ -0,0 +0,0 @@ #!/usr/bin/env node |
{ | ||
"name": "@wang1212/create-web-app", | ||
"version": "0.3.2", | ||
"version": "0.3.11", | ||
"keywords": [ | ||
@@ -5,0 +5,0 @@ "web-app", |
@@ -14,6 +14,6 @@ /* eslint-disable */ | ||
proxy: { | ||
open: false, | ||
open: true, | ||
port: 3000, | ||
proxy: 'http://localhost:8181/App/' | ||
} | ||
proxy: 'http://localhost:8181/App/', | ||
}, | ||
}) |
@@ -93,2 +93,4 @@ /* eslint-disable */ | ||
name: (entrypoint) => `runtime-${entrypoint.name}`, | ||
// multiple entry points | ||
// name: 'single', | ||
}, | ||
@@ -101,2 +103,3 @@ }, | ||
utils: path.resolve('./src/utils/'), | ||
assets: path.resolve('./src/assets/'), | ||
vendors: path.resolve('./src/vendors/'), | ||
@@ -178,3 +181,16 @@ }, | ||
options: { | ||
attributes: ['img:src', 'img:data-src'], | ||
attributes: { | ||
list: [ | ||
{ | ||
tag: 'img', | ||
attribute: 'src', | ||
type: 'src', | ||
}, | ||
{ | ||
tag: 'img', | ||
attribute: 'data-src', | ||
type: 'src', | ||
}, | ||
], | ||
}, | ||
}, | ||
@@ -226,15 +242,22 @@ }, | ||
}), | ||
new CopyWebpackPlugin([ | ||
{ | ||
from: './public/*.!(ejs)', | ||
to: '.', | ||
flatten: true, | ||
cache: true, | ||
}, | ||
{ | ||
from: './src/vendors', | ||
to: './vendors', | ||
cache: true, | ||
}, | ||
]), | ||
new CopyWebpackPlugin({ | ||
patterns: [ | ||
{ | ||
from: './public/*.!(ejs)', | ||
to: '.', | ||
flatten: true, | ||
cacheTransform: true, | ||
}, | ||
{ | ||
from: './src/assets', | ||
to: './assets', | ||
cacheTransform: true, | ||
}, | ||
{ | ||
from: './src/vendors', | ||
to: './vendors', | ||
cacheTransform: true, | ||
}, | ||
], | ||
}), | ||
new HtmlWebpackPlugin({ | ||
@@ -241,0 +264,0 @@ chunks: ['app'], |
{ | ||
"name": "web-app", | ||
"version": "1.0.0", | ||
"version": "0.1.0", | ||
"description": "PWA(Progressive Web App).", | ||
@@ -23,47 +23,47 @@ "author": "", | ||
"devDependencies": { | ||
"@babel/core": "^7.9.0", | ||
"@babel/core": "^7.9.6", | ||
"@babel/plugin-proposal-class-properties": "^7.8.3", | ||
"@babel/plugin-proposal-object-rest-spread": "^7.9.0", | ||
"@babel/plugin-proposal-object-rest-spread": "^7.9.6", | ||
"@babel/plugin-syntax-dynamic-import": "^7.8.3", | ||
"@babel/preset-env": "^7.9.0", | ||
"@babel/preset-env": "^7.9.6", | ||
"@babel/preset-typescript": "^7.9.0", | ||
"@typescript-eslint/eslint-plugin": "^2.24.0", | ||
"@typescript-eslint/parser": "^2.24.0", | ||
"babel-jest": "^25.1.0", | ||
"@typescript-eslint/eslint-plugin": "^2.33.0", | ||
"@typescript-eslint/parser": "^2.33.0", | ||
"babel-jest": "^26.0.1", | ||
"babel-loader": "^8.1.0", | ||
"browser-sync": "^2.26.7", | ||
"case-sensitive-paths-webpack-plugin": "^2.3.0", | ||
"copy-webpack-plugin": "^5.1.1", | ||
"css-loader": "^3.4.2", | ||
"copy-webpack-plugin": "^6.0.0", | ||
"css-loader": "^3.5.3", | ||
"del": "^5.1.0", | ||
"docdash": "^1.2.0", | ||
"eslint": "^6.8.0", | ||
"eslint-config-prettier": "^6.10.1", | ||
"eslint-plugin-prettier": "^3.1.2", | ||
"eslint": "^7.0.0", | ||
"eslint-config-prettier": "^6.11.0", | ||
"eslint-plugin-prettier": "^3.1.3", | ||
"file-loader": "^6.0.0", | ||
"html-loader": "^1.0.0", | ||
"html-webpack-plugin": "^4.0.0", | ||
"html-loader": "^1.1.0", | ||
"html-webpack-plugin": "^4.3.0", | ||
"image-webpack-loader": "^6.0.0", | ||
"jest": "^25.1.0", | ||
"jsdoc": "^3.6.3", | ||
"jest": "^26.0.1", | ||
"jsdoc": "^3.6.4", | ||
"jsdoc-babel": "^0.5.0", | ||
"mini-css-extract-plugin": "^0.9.0", | ||
"node-sass": "^4.13.1", | ||
"node-sass": "^4.14.1", | ||
"optimize-css-assets-webpack-plugin": "^5.0.3", | ||
"postcss-flexbugs-fixes": "^4.2.0", | ||
"postcss-flexbugs-fixes": "^4.2.1", | ||
"postcss-loader": "^3.0.0", | ||
"postcss-normalize": "^8.0.1", | ||
"postcss-normalize": "^9.0.0", | ||
"postcss-preset-env": "^6.7.0", | ||
"postcss-safe-parser": "^4.0.2", | ||
"prettier": "2.0.1", | ||
"prettier": "2.0.5", | ||
"sass-loader": "^8.0.2", | ||
"style-loader": "^1.1.3", | ||
"terser-webpack-plugin": "^2.3.5", | ||
"typescript": "^3.8.3", | ||
"url-loader": "^4.0.0", | ||
"webpack": "^4.42.0", | ||
"webpack-bundle-analyzer": "^3.6.1", | ||
"workbox-webpack-plugin": "^5.1.1", | ||
"style-loader": "^1.2.1", | ||
"terser-webpack-plugin": "^3.0.1", | ||
"typescript": "^3.9.2", | ||
"url-loader": "^4.1.0", | ||
"webpack": "^4.43.0", | ||
"webpack-bundle-analyzer": "^3.7.0", | ||
"workbox-webpack-plugin": "^5.1.3", | ||
"worker-loader": "^2.0.0" | ||
} | ||
} |
{ | ||
"_version": "1.0.0", | ||
"_version": "0.1.0", | ||
"short_name": "PWA", | ||
@@ -4,0 +4,0 @@ "name": "Web App", |
# Web App | ||
PWA(Progressive Web App),渐进式 Web 应用。 | ||
PWA, Progressive Web App. | ||
@@ -8,88 +8,85 @@ ## Directory Structure | ||
App/ | ||
├── build/ # 压缩、编译后的代码,用于生产环境 | ||
├── docs/ # 项目文档 | ||
| └── jsdoc/ # JSDOC 生成的 API 文档 | ||
|── config/ # 开发环境配置 | ||
| |── nginx.conf # nginx 服务器配置 | ||
| ├── path.config.js # 项目路径配置 | ||
| ├── webpack.config.js # webpack 配置 | ||
| ├── webpack.dll.config.js # webpack 外部依赖配置 | ||
| ├── jest.config.js # jest 代码测试配置 | ||
| └── jsdoc.config.js # jsdoc 文档配置 | ||
|── public/ # 公共静态资源 | ||
| ├── manifest.json # 应用图标,名称信息 | ||
| └── index.ejs # 主页 html 模板 | ||
|── scripts/ # 脚本 | ||
| └── index.js # 启动脚本 | ||
|── src/ # 源代码 | ||
| ├── components/ # 组件 | ||
| | └── shared/ # 公共组件 | ||
| ├── reduxs/ # redux 配置文件 | ||
| ├── utils/ # 工具组件、常量 | ||
| ├── vendors/ # 外部依赖 | ||
├── build/ | ||
├── docs/ | ||
| └── jsdoc/ | ||
|── config/ | ||
| |── nginx.conf | ||
| ├── path.config.js | ||
| ├── webpack.config.js | ||
| ├── webpack.dll.config.js | ||
| ├── jest.config.js | ||
| └── jsdoc.config.js | ||
|── public/ | ||
| ├── manifest.json | ||
| └── index.ejs | ||
|── scripts/ | ||
| └── index.js | ||
|── src/ | ||
| ├── components/ | ||
| | └── shared/ | ||
| ├── utils/ | ||
| ├── assets/ | ||
| ├── vendors/ | ||
| ├── app.js | ||
| └── app.scss | ||
|── .babelrc.js # babel 编译配置 | ||
|── .eslintrc.json # eslint 代码规则检查配置 | ||
|── .prettierrc.yml # prettier 代码格式化配置 | ||
|── tsconfig.json # typescript 配置文件 | ||
└── CHANGELOG.md # 项目迭代更新记录 | ||
|── .babelrc.js | ||
|── .eslintrc.json | ||
|── .prettierrc.yml | ||
|── tsconfig.json | ||
└── CHANGELOG.md | ||
## Features | ||
- [SPA](https://en.wikipedia.org/wiki/Single-page_application) - 应用以 SPA 单页面方式进行构建。 | ||
- [PWA](https://en.wikipedia.org/wiki/Progressive_web_applications) - 使用谷歌的 [WorkBox](https://developers.google.com/web/tools/workbox/) 工具提供的 [workbox-webpack-plugin](https://developers.google.com/web/tools/workbox/modules/workbox-webpack-plugin) 插件来生成 `service-work.js` 文件,对应用数据进行离线缓存。 | ||
- [Webpack](https://webpack.js.org/) - 自动化项目构建,模块化管理、打包、压缩、优化。 | ||
- [Browser-Sync](https://www.browsersync.io/) - 该插件配合 Webpack 实现热重载(hot reload)。 | ||
- [Babel](https://babeljs.io/) - 支持使用 E6/7/8/9 进行编码。 | ||
- [React.js](https://reactjs.org/) - 基于 React 开发。 | ||
- [Redux.js](https://redux.js.org/) - 应用状态管理。 | ||
- [React Router](https://reacttraining.com/react-router/) - 页面路由管理。 | ||
- [TypeScript](http://www.typescriptlang.org/) - 支持使用 TypeScript 进行编码。 | ||
- [ESLint](https://eslint.org/) - 语法规则检查。 | ||
- [Prettier](https://prettier.io/) - 代码格式化。 | ||
- [Jest](https://jestjs.io/) - 单元测试。 | ||
- [JSDoc 3](http://usejsdoc.org/) - 生成 API 文档,因此在开发时注释风格应符合 jsdoc 规则。 | ||
- [Nginx](http://nginx.org/) - 反向代理实现前后端的完全分离开发/部署解决方案。 | ||
- [SPA](https://en.wikipedia.org/wiki/Single-page_application) | ||
- [PWA](https://en.wikipedia.org/wiki/Progressive_web_applications) - use [WorkBox](https://developers.google.com/web/tools/workbox/), [workbox-webpack-plugin](https://developers.google.com/web/tools/workbox/modules/workbox-webpack-plugin). | ||
- [Webpack](https://webpack.js.org/) | ||
- [Browser-Sync](https://www.browsersync.io/) | ||
- [Babel](https://babeljs.io/) | ||
- [TypeScript](http://www.typescriptlang.org/) | ||
- [ESLint](https://eslint.org/) | ||
- [Prettier](https://prettier.io/) | ||
- [Jest](https://jestjs.io/) | ||
- [JSDoc 3](http://usejsdoc.org/) | ||
- [Nginx](http://nginx.org/) | ||
## Usage | ||
下载该项目的所有代码到本地。 | ||
Download all the code of the project to the local. | ||
1. 首先,安装开发环境所有的依赖 | ||
1. First, install all the dependencies of the development environment | ||
npm install | ||
2. 服务器 | ||
2. server | ||
若使用反向代理,需在本地安装好 nginx,配置文件在 **config/nginx.conf** 中,启动 nginx : | ||
If you use a reverse proxy, you need to install nginx locally, the configuration file is in **config/nginx.conf**, start nginx: | ||
start nginx | ||
若不使用反向代理,更改 **scripts/index.js** 中 [BrowserSync](https://www.browsersync.io/) 插件的配置即可。 | ||
If you do not use a reverse proxy, you can change the configuration of the [BrowserSync](https://www.browsersync.io/) plugin in **scripts/index.js**. | ||
3. 启动项目(开发环境) | ||
3. Start the project (development environment) | ||
npm run start | ||
4. 执行代码类型检查 | ||
4. Perform code type checking | ||
针对 `.ts, .tsx` 文件,运行: | ||
For `.ts, .tsx` files, run: | ||
npm run type-check | ||
针对所有文件,运行: | ||
For all files, run: | ||
npm run lint | ||
5. 执行代码测试 | ||
5. Perform code testing | ||
npm run test | ||
6. 生成 jsdoc 文档 | ||
6. Generate jsdoc documentation | ||
npm run doc | ||
7. 构建生产环境代码,将会在 **build/** 目录中生成部署代码 | ||
7. Build the production environment code, the deployment code will be generated in the **build/** directory | ||
npm run build |
@@ -8,6 +8,11 @@ /* App entry file */ | ||
import view from './components/test-ts/index' | ||
import * as serviceWorker from './serviceWorker' | ||
window['App'].innerHTML = ` | ||
window['root'].innerHTML = ` | ||
<h1>App running !</h1> | ||
<p>${view}</p> | ||
` | ||
// app to work offline and load faster | ||
// Learn more about service workers: https://bit.ly/CRA-PWA | ||
serviceWorker.register() |
{ | ||
"compilerOptions": { | ||
"target": "ES5", | ||
"sourceMap": true, | ||
@@ -12,3 +13,3 @@ "rootDir": ".", | ||
"include": ["src", "scripts", "config"], | ||
"exclude": ["node_modules", "docs", "public", "src/vendors/**/*", "**/*.spec.ts"] | ||
"exclude": ["node_modules", "docs", "public", "src/assets/**/*", "src/vendors/**/*", "**/*.spec.ts"] | ||
} |
@@ -9,7 +9,7 @@ module.exports = { | ||
isTSX: true, | ||
allExtensions: true | ||
} | ||
] | ||
allExtensions: true, | ||
}, | ||
], | ||
], | ||
plugins: ['@babel/plugin-syntax-dynamic-import', '@babel/plugin-proposal-class-properties', '@babel/plugin-proposal-object-rest-spread'] | ||
plugins: ['@babel/plugin-syntax-dynamic-import', '@babel/plugin-proposal-class-properties', '@babel/plugin-proposal-object-rest-spread'], | ||
} |
@@ -14,6 +14,6 @@ /* eslint-disable */ | ||
proxy: { | ||
open: false, | ||
open: true, | ||
port: 3000, | ||
proxy: 'http://localhost:8181/App/' | ||
} | ||
proxy: 'http://localhost:8181/App/', | ||
}, | ||
}) |
@@ -93,2 +93,4 @@ /* eslint-disable */ | ||
name: (entrypoint) => `runtime-${entrypoint.name}`, | ||
// multiple entry points | ||
// name: 'single', | ||
}, | ||
@@ -102,2 +104,3 @@ }, | ||
utils: path.resolve('./src/utils/'), | ||
assets: path.resolve('./src/assets/'), | ||
vendors: path.resolve('./src/vendors/'), | ||
@@ -179,3 +182,16 @@ }, | ||
options: { | ||
attributes: ['img:src', 'img:data-src'], | ||
attributes: { | ||
list: [ | ||
{ | ||
tag: 'img', | ||
attribute: 'src', | ||
type: 'src', | ||
}, | ||
{ | ||
tag: 'img', | ||
attribute: 'data-src', | ||
type: 'src', | ||
}, | ||
], | ||
}, | ||
}, | ||
@@ -227,15 +243,22 @@ }, | ||
}), | ||
new CopyWebpackPlugin([ | ||
{ | ||
from: './public/*.!(ejs)', | ||
to: '.', | ||
flatten: true, | ||
cache: true, | ||
}, | ||
{ | ||
from: './src/vendors', | ||
to: './vendors', | ||
cache: true, | ||
}, | ||
]), | ||
new CopyWebpackPlugin({ | ||
patterns: [ | ||
{ | ||
from: './public/*.!(ejs)', | ||
to: '.', | ||
flatten: true, | ||
cacheTransform: true, | ||
}, | ||
{ | ||
from: './src/assets', | ||
to: './assets', | ||
cacheTransform: true, | ||
}, | ||
{ | ||
from: './src/vendors', | ||
to: './vendors', | ||
cacheTransform: true, | ||
}, | ||
], | ||
}), | ||
new HtmlWebpackPlugin({ | ||
@@ -242,0 +265,0 @@ chunks: ['app'], |
{ | ||
"name": "web-app-with-react", | ||
"version": "1.0.0", | ||
"version": "0.1.0", | ||
"description": "Based on React.js, Redux, React-Router, PWA (Progressive Web App), progressive web application.", | ||
@@ -26,3 +26,3 @@ "author": "", | ||
"react-redux": "^7.2.0", | ||
"react-router-dom": "^5.1.2", | ||
"react-router-dom": "^5.2.0", | ||
"redux": "^4.0.5", | ||
@@ -33,55 +33,55 @@ "redux-thunk": "^2.3.0", | ||
"devDependencies": { | ||
"@babel/core": "^7.9.0", | ||
"@babel/core": "^7.9.6", | ||
"@babel/plugin-proposal-class-properties": "^7.8.3", | ||
"@babel/plugin-proposal-object-rest-spread": "^7.9.0", | ||
"@babel/plugin-proposal-object-rest-spread": "^7.9.6", | ||
"@babel/plugin-syntax-dynamic-import": "^7.8.3", | ||
"@babel/preset-env": "^7.9.0", | ||
"@babel/preset-react": "^7.9.1", | ||
"@babel/preset-env": "^7.9.6", | ||
"@babel/preset-react": "^7.9.4", | ||
"@babel/preset-typescript": "^7.9.0", | ||
"@types/loadable__component": "^5.10.0", | ||
"@types/react": "^16.9.25", | ||
"@types/react-redux": "^7.1.7", | ||
"@types/react-router-dom": "^5.1.3", | ||
"@typescript-eslint/eslint-plugin": "^2.24.0", | ||
"@typescript-eslint/parser": "^2.24.0", | ||
"babel-jest": "^25.1.0", | ||
"@types/react": "^16.9.35", | ||
"@types/react-redux": "^7.1.8", | ||
"@types/react-router-dom": "^5.1.5", | ||
"@typescript-eslint/eslint-plugin": "^2.33.0", | ||
"@typescript-eslint/parser": "^2.33.0", | ||
"babel-jest": "^26.0.1", | ||
"babel-loader": "^8.1.0", | ||
"browser-sync": "^2.26.7", | ||
"case-sensitive-paths-webpack-plugin": "^2.3.0", | ||
"copy-webpack-plugin": "^5.1.1", | ||
"css-loader": "^3.4.2", | ||
"copy-webpack-plugin": "^6.0.0", | ||
"css-loader": "^3.5.3", | ||
"del": "^5.1.0", | ||
"docdash": "^1.2.0", | ||
"eslint": "^6.8.0", | ||
"eslint-config-prettier": "^6.10.1", | ||
"eslint-plugin-prettier": "^3.1.2", | ||
"eslint-plugin-react": "^7.19.0", | ||
"eslint-plugin-react-hooks": "^2.5.1", | ||
"eslint": "^7.0.0", | ||
"eslint-config-prettier": "^6.11.0", | ||
"eslint-plugin-prettier": "^3.1.3", | ||
"eslint-plugin-react": "^7.20.0", | ||
"eslint-plugin-react-hooks": "^4.0.2", | ||
"file-loader": "^6.0.0", | ||
"html-loader": "^1.0.0", | ||
"html-webpack-plugin": "^4.0.0", | ||
"html-loader": "^1.1.0", | ||
"html-webpack-plugin": "^4.3.0", | ||
"image-webpack-loader": "^6.0.0", | ||
"jest": "^25.1.0", | ||
"jsdoc": "^3.6.3", | ||
"jest": "^26.0.1", | ||
"jsdoc": "^3.6.4", | ||
"jsdoc-babel": "^0.5.0", | ||
"mini-css-extract-plugin": "^0.9.0", | ||
"node-sass": "^4.13.1", | ||
"node-sass": "^4.14.1", | ||
"optimize-css-assets-webpack-plugin": "^5.0.3", | ||
"postcss-flexbugs-fixes": "^4.2.0", | ||
"postcss-flexbugs-fixes": "^4.2.1", | ||
"postcss-loader": "^3.0.0", | ||
"postcss-normalize": "^8.0.1", | ||
"postcss-normalize": "^9.0.0", | ||
"postcss-preset-env": "^6.7.0", | ||
"postcss-safe-parser": "^4.0.2", | ||
"prettier": "2.0.1", | ||
"prettier": "2.0.5", | ||
"redux-logger": "^3.0.6", | ||
"sass-loader": "^8.0.2", | ||
"style-loader": "^1.1.3", | ||
"terser-webpack-plugin": "^2.3.5", | ||
"typescript": "^3.8.3", | ||
"url-loader": "^4.0.0", | ||
"webpack": "^4.42.0", | ||
"webpack-bundle-analyzer": "^3.6.1", | ||
"workbox-webpack-plugin": "^5.1.1", | ||
"style-loader": "^1.2.1", | ||
"terser-webpack-plugin": "^3.0.1", | ||
"typescript": "^3.9.2", | ||
"url-loader": "^4.1.0", | ||
"webpack": "^4.43.0", | ||
"webpack-bundle-analyzer": "^3.7.0", | ||
"workbox-webpack-plugin": "^5.1.3", | ||
"worker-loader": "^2.0.0" | ||
} | ||
} |
{ | ||
"_version": "1.0.0", | ||
"_version": "0.1.0", | ||
"short_name": "React App", | ||
@@ -4,0 +4,0 @@ "name": "App dev with React", |
# Web App with React.js | ||
构建基于 React.js、Redux、React-Router 开发的 PWA(Progressive Web App),渐进式 Web 应用。 | ||
Build PWA (Progressive Web App) based on React.js, Redux, React-Router. | ||
@@ -8,88 +8,89 @@ ## Directory Structure | ||
App/ | ||
├── build/ # 压缩、编译后的代码,用于生产环境 | ||
├── docs/ # 项目文档 | ||
| └── jsdoc/ # JSDOC 生成的 API 文档 | ||
|── config/ # 开发环境配置 | ||
| |── nginx.conf # nginx 服务器配置 | ||
| ├── path.config.js # 项目路径配置 | ||
| ├── webpack.config.js # webpack 配置 | ||
| ├── webpack.dll.config.js # webpack 外部依赖配置 | ||
| ├── jest.config.js # jest 代码测试配置 | ||
| └── jsdoc.config.js # jsdoc 文档配置 | ||
|── public/ # 公共静态资源 | ||
| ├── manifest.json # 应用图标,名称信息 | ||
| └── index.ejs # 主页 html 模板 | ||
|── scripts/ # 脚本 | ||
| └── index.js # 启动脚本 | ||
|── src/ # 源代码 | ||
| ├── components/ # 组件 | ||
| | └── shared/ # 公共组件 | ||
| ├── reduxs/ # redux 配置文件 | ||
| ├── utils/ # 工具组件、常量 | ||
| ├── vendors/ # 外部依赖 | ||
| ├── app.js | ||
| └── app.scss | ||
|── .babelrc.js # babel 编译配置 | ||
|── .eslintrc.json # eslint 代码规则检查配置 | ||
|── .prettierrc.yml # prettier 代码格式化配置 | ||
|── tsconfig.json # typescript 配置文件 | ||
└── CHANGELOG.md # 项目迭代更新记录 | ||
├── build/ | ||
├── docs/ | ||
| └── jsdoc/ | ||
|── config/ | ||
| |── nginx.conf | ||
| ├── path.config.js | ||
| ├── webpack.config.js | ||
| ├── webpack.dll.config.js | ||
| ├── jest.config.js | ||
| └── jsdoc.config.js | ||
|── public/ | ||
| ├── manifest.json | ||
| └── index.ejs | ||
|── scripts/ | ||
| └── index.js | ||
|── src/ | ||
| ├── components/ | ||
| | └── shared/ | ||
| ├── reducers/ | ||
| ├── utils/ | ||
| ├── assets/ | ||
| ├── vendors/ | ||
| ├── index.js | ||
| └── index.scss | ||
|── .babelrc.js | ||
|── .eslintrc.json | ||
|── .prettierrc.yml | ||
|── tsconfig.json | ||
└── CHANGELOG.md | ||
## Features | ||
- [SPA](https://en.wikipedia.org/wiki/Single-page_application) - 应用以 SPA 单页面方式进行构建。 | ||
- [PWA](https://en.wikipedia.org/wiki/Progressive_web_applications) - 使用谷歌的 [WorkBox](https://developers.google.com/web/tools/workbox/) 工具提供的 [workbox-webpack-plugin](https://developers.google.com/web/tools/workbox/modules/workbox-webpack-plugin) 插件来生成 `service-work.js` 文件,对应用数据进行离线缓存。 | ||
- [Webpack](https://webpack.js.org/) - 自动化项目构建,模块化管理、打包、压缩、优化。 | ||
- [Browser-Sync](https://www.browsersync.io/) - 该插件配合 Webpack 实现热重载(hot reload)。 | ||
- [Babel](https://babeljs.io/) - 支持使用 E6/7/8/9 进行编码。 | ||
- [React.js](https://reactjs.org/) - 基于 React 开发。 | ||
- [Redux.js](https://redux.js.org/) - 应用状态管理。 | ||
- [React Router](https://reacttraining.com/react-router/) - 页面路由管理。 | ||
- [TypeScript](http://www.typescriptlang.org/) - 支持使用 TypeScript 进行编码。 | ||
- [ESLint](https://eslint.org/) - 语法规则检查。 | ||
- [Prettier](https://prettier.io/) - 代码格式化。 | ||
- [Jest](https://jestjs.io/) - 单元测试。 | ||
- [JSDoc 3](http://usejsdoc.org/) - 生成 API 文档,因此在开发时注释风格应符合 jsdoc 规则。 | ||
- [Nginx](http://nginx.org/) - 反向代理实现前后端的完全分离开发/部署解决方案。 | ||
- [SPA](https://en.wikipedia.org/wiki/Single-page_application) | ||
- [PWA](https://en.wikipedia.org/wiki/Progressive_web_applications) - use [WorkBox](https://developers.google.com/web/tools/workbox/), [workbox-webpack-plugin](https://developers.google.com/web/tools/workbox/modules/workbox-webpack-plugin). | ||
- [Webpack](https://webpack.js.org/) | ||
- [Browser-Sync](https://www.browsersync.io/) | ||
- [Babel](https://babeljs.io/) | ||
- [React.js](https://reactjs.org/) | ||
- [Redux.js](https://redux.js.org/) | ||
- [React Router](https://reacttraining.com/react-router/) | ||
- [TypeScript](http://www.typescriptlang.org/) | ||
- [ESLint](https://eslint.org/) | ||
- [Prettier](https://prettier.io/) | ||
- [Jest](https://jestjs.io/) | ||
- [JSDoc 3](http://usejsdoc.org/) | ||
- [Nginx](http://nginx.org/) | ||
## Usage | ||
下载该项目的所有代码到本地。 | ||
Download all the code of the project to the local. | ||
1. 首先,安装开发环境所有的依赖 | ||
1. First, install all the dependencies of the development environment | ||
npm install | ||
2. 服务器 | ||
2. server | ||
若使用反向代理,需在本地安装好 nginx,配置文件在 **config/nginx.conf** 中,启动 nginx : | ||
If you use a reverse proxy, you need to install nginx locally, the configuration file is in **config/nginx.conf**, start nginx: | ||
start nginx | ||
若不使用反向代理,更改 **scripts/index.js** 中 [BrowserSync](https://www.browsersync.io/) 插件的配置即可。 | ||
If you do not use a reverse proxy, you can change the configuration of the [BrowserSync](https://www.browsersync.io/) plugin in **scripts/index.js**. | ||
3. 启动项目(开发环境) | ||
3. Start the project (development environment) | ||
npm run start | ||
4. 执行代码类型检查 | ||
4. Perform code type checking | ||
针对 `.ts, .tsx` 文件,运行: | ||
For `.ts, .tsx` files, run: | ||
npm run type-check | ||
针对所有文件,运行: | ||
For all files, run: | ||
npm run lint | ||
5. 执行代码测试 | ||
5. Perform code testing | ||
npm run test | ||
6. 生成 jsdoc 文档 | ||
6. Generate jsdoc documentation | ||
npm run doc | ||
7. 构建生产环境代码,将会在 **build/** 目录中生成部署代码 | ||
7. Build the production environment code, the deployment code will be generated in the **build/** directory | ||
npm run build |
@@ -11,8 +11,18 @@ /* App entry file */ | ||
import App from './components/App' | ||
import * as serviceWorker from './serviceWorker' | ||
const AppRootDOM = document.getElementById('App') | ||
const RootDOM = document.getElementById('root') | ||
/* Render to dom */ | ||
if (AppRootDOM) { | ||
render(<App />, AppRootDOM) | ||
render( | ||
<React.StrictMode> | ||
<App /> | ||
</React.StrictMode>, | ||
RootDOM | ||
) | ||
} | ||
// app to work offline and load faster | ||
// Learn more about service workers: https://bit.ly/CRA-PWA | ||
serviceWorker.register() |
{ | ||
"compilerOptions": { | ||
"target": "ES5", | ||
"sourceMap": true, | ||
@@ -13,3 +14,3 @@ "jsx": "preserve", | ||
"include": ["src", "scripts", "config"], | ||
"exclude": ["node_modules", "docs", "public", "src/vendors/**/*", "**/*.spec.ts"] | ||
"exclude": ["node_modules", "docs", "public", "src/assets/**/*", "src/vendors/**/*", "**/*.spec.ts"] | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
183284
98
2392
2