├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── index.js ├── package.json ├── template-deno-oak ├── .env ├── README.md ├── _gitignore ├── app.ts ├── deps.ts └── routes.ts ├── template-deno-vscode-cmd ├── .vscode │ └── typescript.code-snippets └── cmd.ts ├── template-react-dva-ts ├── README.md ├── _gitignore ├── index.html ├── package.json ├── src │ ├── core │ │ ├── dva.ts │ │ └── init.tsx │ ├── example │ │ ├── Layout.tsx │ │ ├── Login.tsx │ │ ├── Protected.tsx │ │ ├── SignOut.tsx │ │ └── style.css │ ├── global.css │ ├── main.tsx │ ├── models │ │ ├── global.ts │ │ └── index.ts │ ├── react-app-env.d.ts │ ├── router │ │ ├── RouteWithSubRoutes.tsx │ │ ├── Router.tsx │ │ └── types.ts │ └── routes.ts ├── tsconfig.json └── vite.config.ts ├── template-wasm-react ├── README.md ├── _gitignore ├── index.html ├── package.json ├── public │ └── favicon.ico ├── src │ ├── App.css │ ├── App.tsx │ ├── index.css │ ├── logo.svg │ ├── main.tsx │ └── vite-env.d.ts ├── tsconfig.json └── vite.config.ts └── template-wasm-vue ├── README.md ├── _gitignore ├── index.html ├── package.json ├── public └── favicon.ico ├── src ├── App.vue ├── assets │ └── logo.png ├── components │ ├── HelloWasm.vue │ └── HelloWorld.vue ├── main.ts ├── shims-vue.d.ts └── vite-env.d.ts ├── tsconfig.json └── vite.config.ts /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | node_modules 4 | dist 5 | *.lock 6 | yarn-error.log 7 | 8 | # rust 9 | target/ 10 | Cargo.lock 11 | pkg/ 12 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # CHANGELOG 2 | 3 | ## 2.4.12 (2021-08-22) 4 | 5 | * ignore the `.rsw/` directory 6 | 7 | ## 2.4.11 (2021-08-22) 8 | 9 | * upgrade dependency (rsw 1.9.0) 10 | 11 | ## 2.4.10 (2021-07-22) 12 | 13 | * upgrade dependency (rsw 1.8.0) 14 | 15 | ## 2.4.9 (2021-07-06) 16 | 17 | * upgrade dependency (rsw 1.6.4) 18 | 19 | ## 2.4.8 (2021-06-19) 20 | 21 | ### Bug Fixes 22 | 23 | * no package.json in generated project (#1) 24 | 25 | ## 2.4.5 (2021-06-18) 26 | 27 | * add rsw-node 28 | 29 | ## 2.4.1 (2021-06-16) 30 | 31 | * upgrade dependency (rsw 1.6.2) 32 | * add xc-app version 33 | 34 | ## 2.4.0 (2021-06-16) 35 | 36 | * upgrade dependency (rsw 1.6.1) 37 | 38 | ## 2.3.4 (2021-04-11) 39 | 40 | * upgrade dependency 41 | * add awesome-rsw 42 | 43 | ## 2.3.3 (2021-04-05) 44 | 45 | * upgrade dependency 46 | 47 | ## 2.3.2 (2021-04-03) 48 | 49 | * upgrade dependency 50 | 51 | ## 2.3.1 (2021-02-20) 52 | 53 | ### Bug Fixes 54 | 55 | * update prompt message based on user input 56 | 57 | ## 2.3.0 (2021-02-20) 58 | 59 | ### Features 60 | 61 | * use command line options 62 | 63 | ## 2.2.1 (2021-02-19) 64 | 65 | * upgrade dependency 66 | 67 | ## 2.2.0 (2021-02-17) 68 | 69 | #### Features 70 | 71 | * add template-wasm-vue 72 | * upgrade dependency 73 | 74 | ## 2.1.0 (2021-01-20) 75 | 76 | #### Features 77 | 78 | * [x] template-deno-oak 79 | * [x] template-deno-vscode-cmd 80 | * [x] template-react-dva-ts 81 | * [x] template-wasm-react 82 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 lencx 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 | # create-xc-app 2 | 3 | Create a project in seconds! 4 | 5 | > **Compatibility Note:** 6 | > Vite requires [Node.js](https://nodejs.org/en/) version >=12.0.0. 7 | 8 | With NPM: 9 | 10 | ```bash 11 | npm init xc-app 12 | ``` 13 | 14 | With Yarn: 15 | 16 | ```bash 17 | yarn create xc-app 18 | ``` 19 | 20 | Then follow the prompts! 21 | 22 | You can also directly specify the project name and the template you want to use via additional command line options. For example, to scaffold a Vite + WebAssembly + React project, run: 23 | 24 | ```bash 25 | # npm 6.x 26 | npm init xc-app my-wasm-app --template wasm-react 27 | 28 | # npm 7+, extra double-dash is needed: 29 | npm init xc-app my-wasm-app -- --template wasm-react 30 | ``` 31 | 32 | Currently supported template presets include: 33 | 34 | * `react-dva-ts` 35 | * `wasm-react` 36 | * `wasm-vue` 37 | * `deno-oak` 38 | * `deno-vscode-cmd`: Based `deno` and `vscode user snippets`, displaying all `"@cmd: "` commands in the project. 39 | * `snippets` must contain `"@cmd: "` string 40 | * the string must be in the first 10 lines of the file will be matched 41 | * `$ deno run --allow-read --allow-write cmd.ts` - use cache `cmd.output` 42 | * `$ deno run --allow-read --allow-write cmd.ts --update` - update `cmd.output` file 43 | * `$ deno run --allow-read --allow-write cmd.ts --update=tree` - tree structure 44 | 45 | ## Related List 46 | 47 | * [vite-plugin-rsw](https://github.com/lencx/vite-plugin-rsw): wasm-pack plugin for vite@v2. 48 | * [WebAssembly入门](https://lencx.github.io/book/wasm/rust_wasm_frontend.html) 49 | * [WebAssembly Series](https://github.com/lencx/z/discussions/22) 50 | * [🦕 Deno](https://deno.land): A secure runtime for JavaScript and TypeScript. 51 | * [🦕 Oak](https://github.com/oakserver/oak): A middleware framework for Deno's net server. 52 | * [🦕 deno-getfiles](https://github.com/lencx/deno-getfiles): Recursively get all files in a directory 53 | * [Dvajs](https://github.com/dvajs/dva): React and redux based, lightweight and elm-style framework. 54 | * [Vite](https://github.com/vitejs/vite): Native-ESM powered web dev build tool. It's fast. 55 | * [VS Code User Snippets](https://code.visualstudio.com/docs/editor/userdefinedsnippets): Code snippets are templates that make it easier to enter repeating code patterns, such as loops or conditional-statements. 56 | 57 | ## License 58 | 59 | MIT License © 2020 [lencx](https://github.com/lencx) 60 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const fs = require('fs') 4 | const path = require('path') 5 | const argv = require('minimist')(process.argv.slice(2)) 6 | const { prompt } = require('enquirer') 7 | const { 8 | green, 9 | blue, 10 | yellow, 11 | gray, 12 | stripColors 13 | } = require('kolorist') 14 | 15 | const cwd = process.cwd() 16 | 17 | const TEMPLATES = [ 18 | ['🦀', yellow('wasm-react')], 19 | ['🦀', yellow('wasm-vue')], 20 | ['⬢ ', green('react-dva-ts')], 21 | ['🦕', blue('deno-oak')], 22 | ['🦕', blue('deno-vscode-cmd')], 23 | ] 24 | 25 | const renameFiles = { 26 | _gitignore: '.gitignore' 27 | } 28 | 29 | async function init() { 30 | let targetDir = argv._[0] 31 | if (!targetDir) { 32 | /** 33 | * @type {{ name: string }} 34 | */ 35 | const { name } = await prompt({ 36 | type: 'input', 37 | name: 'name', 38 | message: `Project name:`, 39 | initial: 'vite-project' 40 | }) 41 | targetDir = name 42 | } 43 | 44 | const pkgName = await getValidPackageName(targetDir) 45 | const root = path.join(cwd, targetDir) 46 | console.log(`\nScaffolding project in ${root}...`) 47 | 48 | if (!fs.existsSync(root)) { 49 | fs.mkdirSync(root, { recursive: true }) 50 | } else { 51 | const existing = fs.readdirSync(root) 52 | if (existing.length) { 53 | /** 54 | * @type {{ yes: boolean }} 55 | */ 56 | const { yes } = await prompt({ 57 | type: 'confirm', 58 | name: 'yes', 59 | initial: 'Y', 60 | message: 61 | `Target directory ${targetDir} is not empty.\n` + 62 | `Remove existing files and continue?` 63 | }) 64 | if (yes) { 65 | emptyDir(root) 66 | } else { 67 | return 68 | } 69 | } 70 | } 71 | 72 | // determine template 73 | let template = argv.t || argv.template 74 | let message = 'Select a template:' 75 | let isValidTemplate = false 76 | let templateSymbol = '' 77 | 78 | // --template expects a value 79 | if (typeof template === 'string') { 80 | const availableTemplates = TEMPLATES.map((template) => stripColors(template[1])) 81 | isValidTemplate = availableTemplates.includes(template) 82 | message = `${template} isn't a valid template. Please choose from below:` 83 | } 84 | 85 | if (!template || !isValidTemplate) { 86 | /** 87 | * @type {{ t: string }} 88 | */ 89 | const { t } = await prompt({ 90 | type: 'select', 91 | name: 't', 92 | message, 93 | choices: TEMPLATES.map(i => i.join(' ~> ')) 94 | }) 95 | 96 | const temp = t.split(' ~> ') 97 | template = stripColors(temp[1]) 98 | templateSymbol = temp[0] 99 | } 100 | 101 | const templateDir = path.join(__dirname, `template-${template}`) 102 | 103 | const write = (file, content) => { 104 | const targetPath = renameFiles[file] 105 | ? path.join(root, renameFiles[file]) 106 | : path.join(root, file) 107 | if (content) { 108 | fs.writeFileSync(targetPath, content) 109 | } else { 110 | copy(path.join(templateDir, file), targetPath) 111 | } 112 | } 113 | 114 | const cmdCd = () => { 115 | console.log(`\nDone. Now run:\n`) 116 | if (root !== cwd) { 117 | console.log(` cd ${path.relative(cwd, root)}`) 118 | } 119 | } 120 | 121 | const files = fs.readdirSync(templateDir) 122 | for (const file of files) { 123 | write(file) 124 | 125 | if (file === 'package.json') { 126 | const pkg = require(path.join(templateDir, `package.json`)) 127 | pkg.name = pkgName 128 | write('package.json', JSON.stringify(pkg, null, 2)) 129 | 130 | const isWasm = ['🦀'].includes(templateSymbol) || /wasm-/.test(template) 131 | 132 | cmdCd() 133 | cmdNode(isWasm) 134 | } 135 | } 136 | } 137 | 138 | function cmdNode(isWasm) { 139 | const pkgManager = /yarn/.test(process.env.npm_execpath) ? 'yarn' : 'npm' 140 | 141 | console.log(` ${pkgManager === 'yarn' ? `yarn` : `npm install`}`) 142 | console.log(` ${pkgManager === 'yarn' ? `yarn dev` : `npm run dev`}`) 143 | isWasm && console.log(` ${pkgManager === 'yarn' ? `yarn rsw:build` : `npm run rsw:build`}`) 144 | console.log() 145 | isWasm && wasmLink() 146 | } 147 | 148 | function wasmLink() { 149 | console.log(gray(`--------------------------------------- 150 | [Rust]: https://www.rust-lang.org 151 | [wasm-pack]: https://github.com/rustwasm/wasm-pack 152 | [vite-plugin-rsw]: https://github.com/lencx/vite-plugin-rsw 153 | [rsw-node]: https://github.com/lencx/rsw-node 154 | [learn-wasm]: https://github.com/lencx/learn-wasm 155 | [awesome-rsw]: https://github.com/lencx/awesome-rsw 156 | [WebAssembly Series](https://github.com/lencx/z/discussions/22) 157 | `)) 158 | } 159 | 160 | function copy(src, dest) { 161 | const stat = fs.statSync(src) 162 | if (stat.isDirectory()) { 163 | copyDir(src, dest) 164 | } else { 165 | fs.copyFileSync(src, dest) 166 | } 167 | } 168 | 169 | function copyDir(srcDir, destDir) { 170 | fs.mkdirSync(destDir, { recursive: true }) 171 | for (const file of fs.readdirSync(srcDir)) { 172 | const srcFile = path.resolve(srcDir, file) 173 | const destFile = path.resolve(destDir, file) 174 | copy(srcFile, destFile) 175 | } 176 | } 177 | 178 | function emptyDir(dir) { 179 | if (!fs.existsSync(dir)) { 180 | return 181 | } 182 | for (const file of fs.readdirSync(dir)) { 183 | const abs = path.resolve(dir, file) 184 | // baseline is Node 12 so can't use rmSync :( 185 | if (fs.lstatSync(abs).isDirectory()) { 186 | emptyDir(abs) 187 | fs.rmdirSync(abs) 188 | } else { 189 | fs.unlinkSync(abs) 190 | } 191 | } 192 | } 193 | 194 | async function getValidPackageName(projectName) { 195 | const packageNameRegExp = /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/ 196 | if (packageNameRegExp.test(projectName)) { 197 | return projectName 198 | } else { 199 | const suggestedPackageName = projectName 200 | .trim() 201 | .toLowerCase() 202 | .replace(/\s+/g, '-') 203 | .replace(/^[._]/, '') 204 | .replace(/[^a-z0-9-~]+/g, '-') 205 | 206 | /** 207 | * @type {{ inputPackageName: string }} 208 | */ 209 | const { inputPackageName } = await prompt({ 210 | type: 'input', 211 | name: 'inputPackageName', 212 | message: `Package name:`, 213 | initial: suggestedPackageName, 214 | validate: (input) => 215 | packageNameRegExp.test(input) ? true : 'Invalid package.json name' 216 | }) 217 | return inputPackageName 218 | } 219 | } 220 | 221 | init().catch((e) => { 222 | console.error(e) 223 | }) 224 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "create-xc-app", 3 | "version": "2.4.12", 4 | "license": "MIT", 5 | "author": "lencx ", 6 | "main": "index.js", 7 | "bin": { 8 | "create-xc-app": "index.js", 9 | "xc": "index.js" 10 | }, 11 | "files": [ 12 | "index.js", 13 | "template-*" 14 | ], 15 | "keywords": [ 16 | "xc", 17 | "rsw", 18 | "wasm", 19 | "vite", 20 | "deno", 21 | "xc-app", 22 | "wasm-vue", 23 | "wasm-react", 24 | "webAssembly" 25 | ], 26 | "repository": { 27 | "type": "git", 28 | "url": "git+https://github.com/lencx/create-xc-app.git" 29 | }, 30 | "bugs": { 31 | "url": "https://github.com/lencx/create-xc-app/issues" 32 | }, 33 | "engines": { 34 | "node": ">=12.0.0" 35 | }, 36 | "homepage": "https://github.com/lencx/create-xc-app/tree/master/#readme", 37 | "dependencies": { 38 | "enquirer": "^2.3.6", 39 | "kolorist": "^1.2.10", 40 | "minimist": "^1.2.5" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /template-deno-oak/.env: -------------------------------------------------------------------------------- 1 | PORT=6300 -------------------------------------------------------------------------------- /template-deno-oak/README.md: -------------------------------------------------------------------------------- 1 | # deno-oak 2 | 3 | ```bash 4 | deno run --allow-net --allow-read app.ts 5 | ``` 6 | 7 | More templates please see [create-xc-app](https://github.com/lencx/create-xc-app) 8 | -------------------------------------------------------------------------------- /template-deno-oak/_gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store -------------------------------------------------------------------------------- /template-deno-oak/app.ts: -------------------------------------------------------------------------------- 1 | import { Application, dotEnvConfig } from './deps.ts'; 2 | import router from './routes.ts'; 3 | 4 | const app = new Application(); 5 | const env = dotEnvConfig(); 6 | 7 | const port = +env.PORT || 6300; 8 | 9 | app.use(router.routes()); 10 | app.use(router.allowedMethods()); 11 | 12 | app.addEventListener('listen', ({ secure, hostname, port }) => { 13 | const protocol = secure ? 'https' : 'http'; 14 | const url = `${protocol}://${hostname ?? 'localhost'}:${port}`; 15 | console.log(`\n🚀 ${url}`); 16 | }) 17 | 18 | await app.listen({ port }); -------------------------------------------------------------------------------- /template-deno-oak/deps.ts: -------------------------------------------------------------------------------- 1 | export { Application, Router } from 'https://deno.land/x/oak/mod.ts'; 2 | export { config as dotEnvConfig } from 'https://deno.land/x/dotenv/mod.ts'; -------------------------------------------------------------------------------- /template-deno-oak/routes.ts: -------------------------------------------------------------------------------- 1 | import { Router } from './deps.ts'; 2 | 3 | const router = new Router(); 4 | 5 | router 6 | .get('/', ({ response }) => { 7 | response.body = 'hello, deno'; 8 | }); 9 | 10 | export default router; -------------------------------------------------------------------------------- /template-deno-vscode-cmd/.vscode/typescript.code-snippets: -------------------------------------------------------------------------------- 1 | { 2 | "author & create_at": { 3 | "prefix": "lc", 4 | "body": [ 5 | "/**", 6 | " * @author: lencx", 7 | " * @create_at: $CURRENT_MONTH_NAME_SHORT $CURRENT_DATE, $CURRENT_YEAR", 8 | " */", 9 | "", 10 | "$2" 11 | ] 12 | }, 13 | "author & create_at & cmd": { 14 | "prefix": "lcc", 15 | "body": [ 16 | "/**", 17 | " * @author: lencx", 18 | " * @create_at: $CURRENT_MONTH_NAME_SHORT $CURRENT_DATE, $CURRENT_YEAR", 19 | " * @cmd: deno run$1 $TM_FILENAME", 20 | " */", 21 | "", 22 | "$2" 23 | ] 24 | }, 25 | } -------------------------------------------------------------------------------- /template-deno-vscode-cmd/cmd.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @author: lencx 3 | * @create_at: Jun 14, 2020 4 | * @cmd: deno run --allow-read --allow-write cmd.ts [--update[=tree]] 5 | */ 6 | 7 | // Deno + VS Code(User Snippets) 8 | // see: https://code.visualstudio.com/docs/editor/userdefinedsnippets 9 | // 1. `snippets` must contain `@cmd: ` string 10 | // 2. the string must be in the first 10 lines of the file will be matched 11 | 12 | import getFiles, { exists } from 'https://deno.land/x/getfiles/mod.ts'; 13 | import { yellow, green } from 'https://deno.land/std/fmt/colors.ts'; 14 | 15 | const args = Deno.args; 16 | const decoder = new TextDecoder(); 17 | const encoder = new TextEncoder(); 18 | const pathMap = new Map(); 19 | const isUpdate = /--update/.test(args[0]); 20 | const isTree = args[0] === '--update=tree'; 21 | const FILE_NAME = './cmd.output'; 22 | 23 | try { 24 | // read cache file 25 | if (!isUpdate) { 26 | const cmdFile = await Deno.open(FILE_NAME); 27 | await Deno.copy(cmdFile, Deno.stdout) 28 | Deno.exit(); 29 | } else { 30 | // update: delete cmd file 31 | await exists(FILE_NAME) && Deno.remove(FILE_NAME); 32 | } 33 | } catch (e) {} 34 | 35 | // options 36 | // see: https://github.com/lencx/deno-getfiles 37 | const files = getFiles({ 38 | root: '.', 39 | // include: [''], 40 | }); 41 | 42 | let cmdCount = 0; 43 | for (const [index, file] of files.entries()) { 44 | const bytes = await Deno.readFile(file.path); 45 | const content = decoder.decode(bytes); 46 | let fmtTxt; 47 | 48 | content.split('\n').some((line, index) => { 49 | const matchStr = ` \* @cmd: `; 50 | if (new RegExp(matchStr).test(line)) { 51 | const cmd = line.replace(matchStr, ''); 52 | 53 | if (isTree) { 54 | // format: tree 55 | let _path: any = file.path.split(`/${file.name}`); 56 | if (!pathMap.has(_path[0])) { 57 | pathMap.set(_path[0], null); 58 | _path = `[${_path[0]}] 59 | | \`-<${file.name}>`; 60 | } else { 61 | _path = `| \`-<${file.name}>`; 62 | } 63 | fmtTxt = encoder.encode(`${yellow(`${_path}`)}: ${green(cmd)}\n`); 64 | } else { 65 | // format: default 66 | cmdCount += 1; 67 | const fmtCount = `[${String(cmdCount).padStart(2, '0')}]`; 68 | fmtTxt = encoder.encode(`${yellow(`${fmtCount} ${file.path}`)}: ${green(cmd)}\n`); 69 | } 70 | 71 | Deno.stdout.write(fmtTxt); 72 | Deno.writeFile(FILE_NAME, fmtTxt, { append: true }); 73 | return true; 74 | } 75 | if (index > 10) return true; 76 | }) 77 | } -------------------------------------------------------------------------------- /template-react-dva-ts/README.md: -------------------------------------------------------------------------------- 1 | # vite-react-dva-typescript 2 | 3 | ```bash 4 | $ npm install 5 | $ npm dev 6 | $ npm build 7 | 8 | # or 9 | $ yarn 10 | $ yarn dev 11 | $ yarn build 12 | ``` 13 | 14 | ```bash 15 | [src] 16 | |- [components] # public component 17 | |- [example] # demo 18 | |- [core] # dva and initApp 19 | |- [layouts] # layout component 20 | |- [services] # api 21 | |- [models] # store 22 | |- [router] # router component 23 | |- [pages] # page component 24 | |- main.tsx # entry file 25 | |- router.ts # router config 26 | `- ... # other 27 | ``` 28 | 29 | More templates please see [create-xc-app](https://github.com/lencx/create-xc-app) 30 | -------------------------------------------------------------------------------- /template-react-dva-ts/_gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | *.local 5 | -------------------------------------------------------------------------------- /template-react-dva-ts/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Lx APP 7 | 8 | 9 |
10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /template-react-dva-ts/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vite-react-dva-typescript-starter", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "dev": "vite", 6 | "build": "tsc && vite build" 7 | }, 8 | "dependencies": { 9 | "react": "^17.0.0", 10 | "react-dom": "^17.0.0", 11 | "dva": "^2.6.0-beta.20", 12 | "dva-core": "^2.0.2", 13 | "dva-loading": "^3.0.20", 14 | "react-redux": "^7.2.0", 15 | "react-router": "^5.2.0", 16 | "react-router-dom": "^5.2.0" 17 | }, 18 | "devDependencies": { 19 | "@types/react": "^17.0.0", 20 | "@types/react-dom": "^17.0.0", 21 | "@vitejs/plugin-react-refresh": "^1.3.1", 22 | "typescript": "^4.1.3", 23 | "vite": "^2.3.7" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /template-react-dva-ts/src/core/dva.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @author: lencx 3 | * @create_at: Jul 04, 2020 4 | */ 5 | 6 | // @ts-ignore 7 | import { create } from 'dva-core'; 8 | // @ts-ignore 9 | import createLoading from 'dva-loading'; 10 | import { Model, Dispatch, DvaInstance } from 'dva'; 11 | 12 | export interface DvaOption { 13 | initialState: object; 14 | models: Model[]; 15 | } 16 | 17 | export type DvaApp = DvaInstance & { 18 | _store: any; 19 | getStore: () => any; 20 | dispatch: Dispatch; 21 | } 22 | 23 | export default function createApp(opt: DvaOption): DvaApp { 24 | const app: DvaApp = create(opt); 25 | let registered: boolean = false; 26 | 27 | app.use(createLoading({})); 28 | 29 | if (!registered) { 30 | opt.models.forEach((model: Model) => app.model(model)); 31 | } 32 | registered = true; 33 | app.start(); 34 | 35 | const store: any = app._store; 36 | app.getStore = () => store; 37 | app.use({ 38 | onError(err: Error){ 39 | console.log(err); 40 | } 41 | }); 42 | 43 | app.dispatch = store.dispatch; 44 | return app; 45 | } 46 | -------------------------------------------------------------------------------- /template-react-dva-ts/src/core/init.tsx: -------------------------------------------------------------------------------- 1 | /** 2 | * @author: lencx 3 | * @create_at: Jul 04, 2020 4 | */ 5 | 6 | import React, { StrictMode, lazy } from 'react'; 7 | import { Provider } from 'react-redux'; 8 | import { BrowserRouter } from 'react-router-dom'; 9 | 10 | import createApp from '/@core/dva'; 11 | import Router, { RouteOption } from '/@route/Router'; 12 | import models from '/@/models'; 13 | 14 | const dvaApp = createApp({ 15 | initialState: {}, 16 | models, 17 | }); 18 | 19 | const store = dvaApp.getStore(); 20 | 21 | interface InitAppProps { 22 | routes: RouteOption[]; 23 | } 24 | 25 | export default function InitApp({ routes }: InitAppProps) { 26 | return ( 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | ) 35 | } 36 | -------------------------------------------------------------------------------- /template-react-dva-ts/src/example/Layout.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Link } from 'react-router-dom'; 3 | import { connect } from 'dva'; 4 | 5 | import Router from '/@route/Router'; 6 | import { RouteOption } from '/@route/types'; 7 | import './style.css'; 8 | 9 | interface LayoutProps { 10 | authenticated: boolean; 11 | routes: RouteOption[]; 12 | } 13 | 14 | function Layout(props: LayoutProps) { 15 | const authenticated = props.authenticated; 16 | return ( 17 |
18 | 26 |
27 | 28 |
29 |
30 | ) 31 | } 32 | 33 | export default connect((state: any) => ({ 34 | authenticated: state.global.authenticated, 35 | }))(Layout) 36 | -------------------------------------------------------------------------------- /template-react-dva-ts/src/example/Login.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Link, useHistory } from 'react-router-dom'; 3 | import { useDispatch } from 'react-redux'; 4 | 5 | export default function Login() { 6 | const dispatch = useDispatch(); 7 | const history = useHistory(); 8 | const handleLogin = () => { 9 | dispatch({ 10 | type: 'global/setState', 11 | payload: { authenticated: true }, 12 | }) 13 | history.push('/protected'); 14 | } 15 | return ( 16 |
17 |

Login Page

18 | 19 | Back To Home 20 |
21 | ) 22 | } 23 | -------------------------------------------------------------------------------- /template-react-dva-ts/src/example/Protected.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default function Protected() { 4 | return ( 5 |
6 |

Protected Page

7 |
8 | ) 9 | } 10 | -------------------------------------------------------------------------------- /template-react-dva-ts/src/example/SignOut.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Link, useHistory } from 'react-router-dom'; 3 | import { useDispatch } from 'react-redux'; 4 | 5 | export default function SignOut() { 6 | const dispatch = useDispatch(); 7 | const history = useHistory(); 8 | const handleOut = () => { 9 | dispatch({ 10 | type: 'global/setState', 11 | payload: { authenticated: false }, 12 | }) 13 | history.push('/login'); 14 | } 15 | return ( 16 |
17 |

SignOut Page

18 | 19 | Back To Home 20 |
21 | ) 22 | } 23 | -------------------------------------------------------------------------------- /template-react-dva-ts/src/example/style.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | background: var(--black); 3 | color: #fff; 4 | height: 100%; 5 | } 6 | 7 | nav { 8 | list-style: none; 9 | } 10 | nav li { 11 | display: inline-block; 12 | } 13 | nav li a { 14 | background: var(--green); 15 | } 16 | 17 | button, a { 18 | display: inline-block; 19 | background: var(--theme-primary); 20 | padding: 0 10px; 21 | height: 30px; 22 | line-height: 30px; 23 | border: none; 24 | border-radius: 10px; 25 | font-size: 14px; 26 | margin: 5px; 27 | color: #fff; 28 | } 29 | 30 | a { 31 | text-decoration: none; 32 | } 33 | 34 | h1 { 35 | font-size: 18px !important; 36 | } 37 | 38 | .main { 39 | padding: 10px; 40 | } -------------------------------------------------------------------------------- /template-react-dva-ts/src/global.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 4 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 12 | monospace; 13 | } 14 | 15 | :root { 16 | --theme-primary: #61dafb; 17 | --green: #4fc08d; 18 | --black: #282c34; 19 | } -------------------------------------------------------------------------------- /template-react-dva-ts/src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | 4 | import InitApp from '/@core/init'; 5 | import routesConfig from '/@/routes'; 6 | import './global.css'; 7 | 8 | ReactDOM.render( 9 | 10 | ,document.getElementById('root') 11 | ); 12 | -------------------------------------------------------------------------------- /template-react-dva-ts/src/models/global.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | namespace: 'global', 3 | state: { 4 | author: `lencx`, 5 | authenticated: false, 6 | }, 7 | reducers: { 8 | setState(state: any, { payload }: any) { 9 | return { ...state, ...payload }; 10 | }, 11 | }, 12 | effects: {}, 13 | } -------------------------------------------------------------------------------- /template-react-dva-ts/src/models/index.ts: -------------------------------------------------------------------------------- 1 | import global from './global'; 2 | 3 | export default [ 4 | global, 5 | // other child models 6 | ]; -------------------------------------------------------------------------------- /template-react-dva-ts/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | declare namespace NodeJS { 5 | interface Process{ 6 | env: ProcessEnv 7 | } 8 | interface ProcessEnv { 9 | /** 10 | * By default, there are two modes in Vite: 11 | * 12 | * * `development` is used by vite and vite serve 13 | * * `production` is used by vite build 14 | * 15 | * You can overwrite the default mode used for a command by passing the --mode option flag. 16 | * 17 | */ 18 | readonly NODE_ENV: 'development' | 'production' 19 | } 20 | } 21 | 22 | declare var process: NodeJS.Process 23 | 24 | declare module '*.gif' { 25 | const src: string 26 | export default src 27 | } 28 | 29 | declare module '*.jpg' { 30 | const src: string 31 | export default src 32 | } 33 | 34 | declare module '*.jpeg' { 35 | const src: string 36 | export default src 37 | } 38 | 39 | declare module '*.png' { 40 | const src: string 41 | export default src 42 | } 43 | 44 | declare module '*.webp' { 45 | const src: string 46 | export default src 47 | } 48 | 49 | declare module '*.svg' { 50 | import * as React from 'react' 51 | 52 | export const ReactComponent: React.FunctionComponent & { title?: string }> 55 | 56 | const src: string; 57 | export default src 58 | } 59 | 60 | declare module '*.module.css' { 61 | const classes: { readonly [key: string]: string } 62 | export default classes 63 | } 64 | 65 | declare module '*.module.scss' { 66 | const classes: { readonly [key: string]: string } 67 | export default classes 68 | } 69 | 70 | declare module '*.module.sass' { 71 | const classes: { readonly [key: string]: string } 72 | export default classes 73 | } -------------------------------------------------------------------------------- /template-react-dva-ts/src/router/RouteWithSubRoutes.tsx: -------------------------------------------------------------------------------- 1 | import React, { Suspense } from 'react'; 2 | import { Redirect, Route } from 'react-router-dom'; 3 | import { useSelector } from 'react-redux' 4 | 5 | import { CONFIG } from '/@/routes'; 6 | import { RouteOption } from './types'; 7 | 8 | const RouteWithSubRoutes = (routeProps: RouteOption) => { 9 | const global = useSelector((state: any) => state.global); 10 | // authenticated flag 11 | const authenticated: boolean = global.authenticated; 12 | 13 | return ( 14 | 15 | { 18 | const comp = routeProps.component && 19 | ; 20 | 21 | return routeProps.redirect 22 | ? 23 | : routeProps.private 24 | ? (authenticated ? comp : ) 25 | : comp 26 | }} 27 | /> 28 | 29 | ); 30 | }; 31 | 32 | export default RouteWithSubRoutes; -------------------------------------------------------------------------------- /template-react-dva-ts/src/router/Router.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Switch } from 'react-router-dom'; 3 | 4 | import RouteWithSubRoutes from './RouteWithSubRoutes'; 5 | import { RouteOption } from './types'; 6 | export * from './types'; 7 | 8 | export interface RouterProps { 9 | routes: RouteOption[]; 10 | } 11 | 12 | const Router: React.FC = ({ routes }) => { 13 | return ( 14 | 15 | {routes.map((route: RouteOption) => )} 16 | 17 | ); 18 | }; 19 | 20 | export default Router; -------------------------------------------------------------------------------- /template-react-dva-ts/src/router/types.ts: -------------------------------------------------------------------------------- 1 | import { ComponentType, LazyExoticComponent, ReactNode } from 'react'; 2 | 3 | export interface RouteOption { 4 | // basic prop 5 | path: string; 6 | // basic prop 7 | exact?: boolean; 8 | // preloader for lazy loading 9 | fallback?: NonNullable | null; 10 | // lazy loaded component 11 | component?: LazyExoticComponent>; 12 | // sub routes 13 | routes?: RouteOption[]; 14 | // redirect path 15 | redirect?: string; 16 | // if router is private, this is going to be true 17 | private?: boolean; 18 | } 19 | -------------------------------------------------------------------------------- /template-react-dva-ts/src/routes.ts: -------------------------------------------------------------------------------- 1 | import { lazy } from 'react'; 2 | import { RouteOption } from '/@route/types'; 3 | 4 | // router config 5 | export const CONFIG = { 6 | // redux: models/global 7 | // authenticated: false, 8 | authRedirect: '/login', 9 | }; 10 | 11 | const routes: RouteOption[] = [ 12 | { 13 | path: '/', 14 | component: lazy(() => import('./example/Layout')), 15 | routes: [ 16 | { 17 | path: '/login', 18 | component: lazy(() => import('./example/Login')), 19 | }, 20 | { 21 | path: '/signout', 22 | component: lazy(() => import('./example/SignOut')), 23 | }, 24 | { 25 | path: '/protected', 26 | private: true, 27 | component: lazy(() => import('./example/Protected')), 28 | }, 29 | ], 30 | }, 31 | ]; 32 | 33 | export default routes; -------------------------------------------------------------------------------- /template-react-dva-ts/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 5 | "types": [], 6 | "allowJs": false, 7 | "skipLibCheck": false, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "module": "ESNext", 13 | "moduleResolution": "Node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "react", 18 | "baseUrl": ".", 19 | "paths": { 20 | "/@/*": ["src/*"], 21 | "/@core/*": ["src/core/*"], 22 | "/@route/*": ["src/router/*"] 23 | } 24 | }, 25 | "include": ["src"] 26 | } -------------------------------------------------------------------------------- /template-react-dva-ts/vite.config.ts: -------------------------------------------------------------------------------- 1 | import * as reactPlugin from 'vite-plugin-react'; 2 | import type { UserConfig } from 'vite'; 3 | import path from 'path'; 4 | 5 | const config: UserConfig = { 6 | jsx: 'react', 7 | plugins: [reactPlugin], 8 | // see: https://github.com/vitejs/vite/blob/master/src/node/config.ts 9 | // the key must start and end with a slash 10 | alias: { 11 | '/@/': path.resolve(__dirname, 'src'), 12 | '/@core/': path.resolve(__dirname, 'src/core'), 13 | '/@route/': path.resolve(__dirname, 'src/router'), 14 | }, 15 | }; 16 | 17 | export default config; -------------------------------------------------------------------------------- /template-wasm-react/README.md: -------------------------------------------------------------------------------- 1 | # wasm-react 2 | 3 | - [WebAssembly Series](https://github.com/lencx/z/discussions/22) 4 | - [learn-wasm](https://github.com/lencx/learn-wasm) 5 | - [vite-plugin-rsw](https://github.com/lencx/vite-plugin-rsw) - 🦀 wasm-pack plugin for Vite 6 | - [rsw-node](https://github.com/lencx/rsw-node) - ⚪️ `wasm-pack build` executed in remote deployment 7 | 8 | ## Quick Start 9 | 10 | ### Step1 11 | 12 | ```bash 13 | npm install 14 | ``` 15 | 16 | ### Step2 17 | 18 | edit `vite.config.ts` 19 | 20 | ```js 21 | // ... 22 | ViteRsw({ 23 | crates: [ 24 | // https://github.com/lencx/vite-plugin-rsw#plugin-options 25 | 'wasm-test', // custom package name 26 | ] 27 | }), 28 | ``` 29 | 30 | ### Step3 31 | 32 | ```bash 33 | npm run dev 34 | ``` 35 | 36 | ## Remote Deployment 37 | 38 | ```bash 39 | npm run rsw:build 40 | ``` 41 | -------------------------------------------------------------------------------- /template-wasm-react/_gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | node_modules 4 | dist 5 | *.local 6 | *.lock 7 | 8 | # rust 9 | target/ 10 | Cargo.lock 11 | pkg/ 12 | /.rsw 13 | -------------------------------------------------------------------------------- /template-wasm-react/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | WASM App 7 | 8 | 9 |
10 | 11 | 12 | -------------------------------------------------------------------------------- /template-wasm-react/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vite-wasm-react-typescript-starter", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "dev": "vite", 6 | "build": "tsc && vite build", 7 | "serve": "vite preview", 8 | "rsw:build": "rsw && npm run build" 9 | }, 10 | "dependencies": { 11 | "react": "^17.0.0", 12 | "react-dom": "^17.0.0" 13 | }, 14 | "devDependencies": { 15 | "@types/react": "^17.0.0", 16 | "@types/react-dom": "^17.0.0", 17 | "@vitejs/plugin-react-refresh": "^1.3.5", 18 | "typescript": "^4.3.2", 19 | "vite": "^2.5.0", 20 | "vite-plugin-rsw": "^1.9.0" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /template-wasm-react/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lencx/create-xc-app/f31c44bc4f4c161c0e77e99c1c0eb831e21f2c73/template-wasm-react/public/favicon.ico -------------------------------------------------------------------------------- /template-wasm-react/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | 40 | button { 41 | font-size: calc(10px + 2vmin); 42 | } 43 | -------------------------------------------------------------------------------- /template-wasm-react/src/App.tsx: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from 'react' 2 | import logo from './logo.svg' 3 | import './App.css' 4 | import init, { greet } from 'wasm-test' 5 | 6 | function App() { 7 | const [count, setCount] = useState(0) 8 | 9 | useEffect(() => { 10 | init() 11 | }, []) 12 | 13 | return ( 14 |
15 |
16 | logo 17 |

Hello WebAssembly!

18 |

Vite + Rust + React

19 |

20 | 23 | {' '} 24 | 27 |

28 |

29 | Edit App.tsx and save to test HMR updates. 30 |

31 |

32 | 38 | Learn React 39 | 40 | {' | '} 41 | 47 | Vite Docs 48 | 49 | {' | '} 50 | 56 | Rsw Docs 57 | 58 |

59 |
60 |
61 | ) 62 | } 63 | 64 | export default App 65 | -------------------------------------------------------------------------------- /template-wasm-react/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /template-wasm-react/src/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /template-wasm-react/src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ReactDOM from 'react-dom' 3 | import './index.css' 4 | import App from './App' 5 | 6 | ReactDOM.render( 7 | 8 | 9 | , 10 | document.getElementById('root') 11 | ) 12 | -------------------------------------------------------------------------------- /template-wasm-react/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// -------------------------------------------------------------------------------- /template-wasm-react/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 5 | "allowJs": false, 6 | "skipLibCheck": false, 7 | "esModuleInterop": false, 8 | "allowSyntheticDefaultImports": true, 9 | "strict": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "module": "ESNext", 12 | "moduleResolution": "Node", 13 | "resolveJsonModule": true, 14 | "isolatedModules": true, 15 | "noEmit": true, 16 | "jsx": "react" 17 | }, 18 | "include": ["./src"] 19 | } 20 | -------------------------------------------------------------------------------- /template-wasm-react/vite.config.ts: -------------------------------------------------------------------------------- 1 | import reactRefresh from '@vitejs/plugin-react-refresh'; 2 | import { defineConfig } from 'vite'; 3 | import ViteRsw from 'vite-plugin-rsw'; 4 | 5 | export default defineConfig({ 6 | plugins: [ 7 | reactRefresh(), 8 | ViteRsw({ 9 | crates: [ 10 | 'wasm-test', 11 | ] 12 | }), 13 | ], 14 | }) 15 | -------------------------------------------------------------------------------- /template-wasm-vue/README.md: -------------------------------------------------------------------------------- 1 | # wasm-vue 2 | 3 | - [WebAssembly Series](https://github.com/lencx/z/discussions/22) 4 | - [learn-wasm](https://github.com/lencx/learn-wasm) 5 | - [vite-plugin-rsw](https://github.com/lencx/vite-plugin-rsw) - 🦀 wasm-pack plugin for Vite 6 | - [rsw-node](https://github.com/lencx/rsw-node) - ⚪️ `wasm-pack build` executed in remote deployment 7 | 8 | ## Quick Start 9 | 10 | ### Step1 11 | 12 | ```bash 13 | npm install 14 | ``` 15 | 16 | ### Step2 17 | 18 | edit `vite.config.ts` 19 | 20 | ```js 21 | // ... 22 | ViteRsw({ 23 | crates: [ 24 | // https://github.com/lencx/vite-plugin-rsw#plugin-options 25 | 'wasm-test', // custom package name 26 | ] 27 | }), 28 | ``` 29 | 30 | ### Step3 31 | 32 | ```bash 33 | npm run dev 34 | ``` 35 | 36 | ## Remote Deployment 37 | 38 | ```bash 39 | npm run rsw:build 40 | ``` 41 | -------------------------------------------------------------------------------- /template-wasm-vue/_gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .DS_Store 3 | dist 4 | dist-ssr 5 | *.local 6 | *.lock 7 | 8 | # rust 9 | target/ 10 | Cargo.lock 11 | pkg/ 12 | /.rsw -------------------------------------------------------------------------------- /template-wasm-vue/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /template-wasm-vue/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vite-rsw-vue-typescript-starter", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "dev": "vite", 6 | "build": "vue-tsc --noEmit && vite build", 7 | "serve": "vite preview", 8 | "rsw:build": "rsw && npm run build" 9 | }, 10 | "dependencies": { 11 | "vue": "^3.0.5" 12 | }, 13 | "devDependencies": { 14 | "@vitejs/plugin-vue": "^1.2.5", 15 | "@vue/compiler-sfc": "^3.0.5", 16 | "typescript": "^4.3.2", 17 | "vite": "^2.5.0", 18 | "vite-plugin-rsw": "^1.9.0", 19 | "vue-tsc": "^0.0.24" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /template-wasm-vue/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lencx/create-xc-app/f31c44bc4f4c161c0e77e99c1c0eb831e21f2c73/template-wasm-vue/public/favicon.ico -------------------------------------------------------------------------------- /template-wasm-vue/src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 20 | 21 | -------------------------------------------------------------------------------- /template-wasm-vue/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lencx/create-xc-app/f31c44bc4f4c161c0e77e99c1c0eb831e21f2c73/template-wasm-vue/src/assets/logo.png -------------------------------------------------------------------------------- /template-wasm-vue/src/components/HelloWasm.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 18 | -------------------------------------------------------------------------------- /template-wasm-vue/src/components/HelloWorld.vue: -------------------------------------------------------------------------------- 1 | 38 | 39 | 55 | 56 | -------------------------------------------------------------------------------- /template-wasm-vue/src/main.ts: -------------------------------------------------------------------------------- 1 | import { createApp } from 'vue' 2 | import App from './App.vue' 3 | 4 | createApp(App).mount('#app') 5 | -------------------------------------------------------------------------------- /template-wasm-vue/src/shims-vue.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.vue' { 2 | import { DefineComponent } from 'vue' 3 | // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/ban-types 4 | const component: DefineComponent<{}, {}, any> 5 | export default component 6 | } -------------------------------------------------------------------------------- /template-wasm-vue/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// -------------------------------------------------------------------------------- /template-wasm-vue/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "esnext", 4 | "module": "esnext", 5 | "moduleResolution": "node", 6 | "strict": true, 7 | "jsx": "preserve", 8 | "sourceMap": true, 9 | "resolveJsonModule": true, 10 | "esModuleInterop": true, 11 | "lib": ["esnext", "dom"] 12 | }, 13 | "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"] 14 | } -------------------------------------------------------------------------------- /template-wasm-vue/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import vue from '@vitejs/plugin-vue'; 3 | import ViteRsw from 'vite-plugin-rsw'; 4 | 5 | // https://vitejs.dev/config/ 6 | export default defineConfig({ 7 | plugins: [ 8 | vue(), 9 | ViteRsw({ 10 | crates: [ 11 | 'wasm-test', 12 | ] 13 | }), 14 | ] 15 | }) 16 | --------------------------------------------------------------------------------