├── .github └── workflows │ └── build-templates.yml ├── .gitignore ├── README.md ├── _template ├── build-pkg.js ├── build.sh └── create-branches.sh ├── package_template.json ├── rollup.config.js ├── scripts └── setupTypeScript.js ├── src ├── ambient.d.ts ├── client.js ├── components │ └── Nav.svelte ├── node_modules │ └── images │ │ └── successkid.jpg ├── routes │ ├── _error.svelte │ ├── _layout.svelte │ ├── about.svelte │ ├── blog │ │ ├── [slug].json.js │ │ ├── [slug].svelte │ │ ├── _posts.js │ │ ├── index.json.js │ │ └── index.svelte │ └── index.svelte ├── server.js ├── service-worker.js └── template.html ├── static ├── favicon.png ├── global.css ├── logo-192.png ├── logo-512.png └── manifest.json └── webpack.config.js /.github/workflows/build-templates.yml: -------------------------------------------------------------------------------- 1 | name: Create templates 2 | on: 3 | push: 4 | branches: 5 | - master 6 | jobs: 7 | build: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v1 11 | - uses: actions/setup-node@v1 12 | - 13 | env: 14 | CI: true 15 | SSH_KEY: ${{ secrets.SSH_KEY }} 16 | SSH_KEY_ROLLUP: ${{ secrets.SSH_KEY_ROLLUP }} 17 | SSH_KEY_WEBPACK: ${{ secrets.SSH_KEY_WEBPACK }} 18 | run: _template/build.sh 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /node_modules/ 3 | /src/node_modules/@sapper/ 4 | yarn-error.log 5 | /__sapper__/ 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # sapper-template 2 | 3 | The default template for setting up a [Sapper](https://github.com/sveltejs/sapper) project. Can use either Rollup or webpack as bundler. 4 | 5 | ## Please note 6 | 7 | Sapper is no longer being actively developed. You may be interested in using Sapper's succesor, [SvelteKit](https://kit.svelte.dev/) for new projects. 8 | 9 | ## Getting started 10 | 11 | ### Using `degit` 12 | 13 | To create a new Sapper project based on Rollup locally, run 14 | 15 | ```bash 16 | npx degit "sveltejs/sapper-template#rollup" my-app 17 | ``` 18 | 19 | For a webpack-based project, instead run 20 | 21 | ```bash 22 | npx degit "sveltejs/sapper-template#webpack" my-app 23 | ``` 24 | 25 | [`degit`](https://github.com/Rich-Harris/degit) is a scaffolding tool that lets you create a directory from a branch in a repository. 26 | 27 | Replace `my-app` with the path where you wish to create the project. 28 | 29 | 30 | ### Using GitHub templates 31 | 32 | Alternatively, you can create the new project as a GitHub repository using GitHub's template feature. 33 | 34 | Go to either [sapper-template-rollup](https://github.com/sveltejs/sapper-template-rollup) or [sapper-template-webpack](https://github.com/sveltejs/sapper-template-webpack) and click on "Use this template" to create a new project repository initialized by the template. 35 | 36 | 37 | ### Running the project 38 | 39 | Once you have created the project, install dependencies and run the project in development mode: 40 | 41 | ```bash 42 | cd my-app 43 | npm install # or yarn 44 | npm run dev 45 | ``` 46 | 47 | This will start the development server on [localhost:3000](http://localhost:3000). Open it and click around. 48 | 49 | You now have a fully functional Sapper project! To get started developing, consult [sapper.svelte.dev](https://sapper.svelte.dev). 50 | 51 | ### Using TypeScript 52 | 53 | By default, the template uses plain JavaScript. If you wish to use TypeScript instead, you need some changes to the project: 54 | 55 | * Add `typescript` as well as typings as dependences in `package.json` 56 | * Configure the bundler to use [`svelte-preprocess`](https://github.com/sveltejs/svelte-preprocess) and transpile the TypeScript code. 57 | * Add a `tsconfig.json` file 58 | * Update the project code to TypeScript 59 | 60 | The template comes with a script that will perform these changes for you by running 61 | 62 | ```bash 63 | node scripts/setupTypeScript.js 64 | ``` 65 | 66 | `@sapper` dependencies are resolved through `src/node_modules/@sapper`, which is created during the build. You therefore need to run or build the project once to avoid warnings about missing dependencies. 67 | 68 | The script does not support webpack at the moment. 69 | 70 | ## Directory structure 71 | 72 | Sapper expects to find two directories in the root of your project — `src` and `static`. 73 | 74 | 75 | ### src 76 | 77 | The [src](src) directory contains the entry points for your app — `client.js`, `server.js` and (optionally) a `service-worker.js` — along with a `template.html` file and a `routes` directory. 78 | 79 | 80 | #### src/routes 81 | 82 | This is the heart of your Sapper app. There are two kinds of routes — *pages*, and *server routes*. 83 | 84 | **Pages** are Svelte components written in `.svelte` files. When a user first visits the application, they will be served a server-rendered version of the route in question, plus some JavaScript that 'hydrates' the page and initialises a client-side router. From that point forward, navigating to other pages is handled entirely on the client for a fast, app-like feel. (Sapper will preload and cache the code for these subsequent pages, so that navigation is instantaneous.) 85 | 86 | **Server routes** are modules written in `.js` files, that export functions corresponding to HTTP methods. Each function receives Express `request` and `response` objects as arguments, plus a `next` function. This is useful for creating a JSON API, for example. 87 | 88 | There are three simple rules for naming the files that define your routes: 89 | 90 | * A file called `src/routes/about.svelte` corresponds to the `/about` route. A file called `src/routes/blog/[slug].svelte` corresponds to the `/blog/:slug` route, in which case `params.slug` is available to the route 91 | * The file `src/routes/index.svelte` (or `src/routes/index.js`) corresponds to the root of your app. `src/routes/about/index.svelte` is treated the same as `src/routes/about.svelte`. 92 | * Files and directories with a leading underscore do *not* create routes. This allows you to colocate helper modules and components with the routes that depend on them — for example you could have a file called `src/routes/_helpers/datetime.js` and it would *not* create a `/_helpers/datetime` route. 93 | 94 | 95 | #### src/node_modules/images 96 | 97 | Images added to `src/node_modules/images` can be imported into your code using `import 'images/'`. They will be given a dynamically generated filename containing a hash, allowing for efficient caching and serving the images on a CDN. 98 | 99 | See [`index.svelte`](src/routes/index.svelte) for an example. 100 | 101 | 102 | #### src/node_modules/@sapper 103 | 104 | This directory is managed by Sapper and generated when building. It contains all the code you import from `@sapper` modules. 105 | 106 | 107 | ### static 108 | 109 | The [static](static) directory contains static assets that should be served publicly. Files in this directory will be available directly under the root URL, e.g. an `image.jpg` will be available as `/image.jpg`. 110 | 111 | The default [service-worker.js](src/service-worker.js) will preload and cache these files, by retrieving a list of `files` from the generated manifest: 112 | 113 | ```js 114 | import { files } from '@sapper/service-worker'; 115 | ``` 116 | 117 | If you have static files you do not want to cache, you should exclude them from this list after importing it (and before passing it to `cache.addAll`). 118 | 119 | Static files are served using [sirv](https://github.com/lukeed/sirv). 120 | 121 | 122 | ## Bundler configuration 123 | 124 | Sapper uses Rollup or webpack to provide code-splitting and dynamic imports, as well as compiling your Svelte components. With webpack, it also provides hot module reloading. As long as you don't do anything daft, you can edit the configuration files to add whatever plugins you'd like. 125 | 126 | 127 | ## Production mode and deployment 128 | 129 | To start a production version of your app, run `npm run build && npm start`. This will disable live reloading, and activate the appropriate bundler plugins. 130 | 131 | You can deploy your application to any environment that supports Node 10 or above. As an example, to deploy to [Vercel Now](https://vercel.com) when using `sapper export`, run these commands: 132 | 133 | ```bash 134 | npm install -g vercel 135 | vercel 136 | ``` 137 | 138 | If your app can't be exported to a static site, you can use the [vercel-sapper](https://github.com/thgh/vercel-sapper) builder. You can find instructions on how to do so in its [README](https://github.com/thgh/vercel-sapper#basic-usage). 139 | 140 | 141 | ## Using external components 142 | 143 | When using Svelte components installed from npm, such as [@sveltejs/svelte-virtual-list](https://github.com/sveltejs/svelte-virtual-list), Svelte needs the original component source (rather than any precompiled JavaScript that ships with the component). This allows the component to be rendered server-side, and also keeps your client-side app smaller. 144 | 145 | Because of that, it's essential that the bundler doesn't treat the package as an *external dependency*. You can either modify the `external` option under `server` in [rollup.config.js](rollup.config.js) or the `externals` option in [webpack.config.js](webpack.config.js), or simply install the package to `devDependencies` rather than `dependencies`, which will cause it to get bundled (and therefore compiled) with your app: 146 | 147 | ```bash 148 | npm install -D @sveltejs/svelte-virtual-list 149 | ``` 150 | 151 | ## Troubleshooting 152 | 153 | Using Windows and WSL2? 154 | 155 | If your project lives outside the WSL root directory, [this limitation](https://github.com/microsoft/WSL/issues/4169) is known to cause live-reloading to fail. See [this issue](https://github.com/sveltejs/sapper/issues/1150) for details. 156 | 157 | ## Bugs and feedback 158 | 159 | Sapper is in early development, and may have the odd rough edge here and there. Please be vocal over on the [Sapper issue tracker](https://github.com/sveltejs/sapper/issues). 160 | -------------------------------------------------------------------------------- /_template/build-pkg.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | 3 | const type = process.argv[2]; 4 | 5 | const pkg = require('../package_template.json'); 6 | for (const key in pkg['merge-configs'][type]) { 7 | Object.assign(pkg[key], pkg['merge-configs'][type][key]); 8 | } 9 | delete pkg['merge-configs']; 10 | fs.writeFileSync( 11 | __dirname + '/../package.json', 12 | JSON.stringify(pkg, null, ' ') + '\n' 13 | ); 14 | -------------------------------------------------------------------------------- /_template/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd "$(dirname "$0")" 3 | 4 | if [ "$CI" ]; then 5 | (umask 0077; echo "$SSH_KEY" > ~/ssh_key; echo "$SSH_KEY_ROLLUP" > ~/ssh_key_rollup; echo "$SSH_KEY_WEBPACK" > ~/ssh_key_webpack) 6 | git config user.email 'noreply@svelte.dev' 7 | git config user.name '[bot]' 8 | fi 9 | 10 | # branch names 11 | ROLLUP=rollup 12 | WEBPACK=webpack 13 | 14 | ./create-branches.sh $ROLLUP $WEBPACK 15 | 16 | # force push rollup and webpack branches and repos 17 | GIT_SSH_COMMAND='ssh -o StrictHostKeyChecking=accept-new -i ~/ssh_key' git push git@github.com:sveltejs/sapper-template.git $ROLLUP $WEBPACK -f 18 | GIT_SSH_COMMAND='ssh -o StrictHostKeyChecking=accept-new -i ~/ssh_key_rollup' git push git@github.com:sveltejs/sapper-template-rollup.git $ROLLUP:master -f 19 | GIT_SSH_COMMAND='ssh -o StrictHostKeyChecking=accept-new -i ~/ssh_key_webpack' git push git@github.com:sveltejs/sapper-template-webpack.git $WEBPACK:master -f 20 | -------------------------------------------------------------------------------- /_template/create-branches.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cd "$(dirname "$0")"/.. 3 | 4 | HEAD=$(git rev-parse HEAD) 5 | 6 | ROLLUP=${1:-rollup} 7 | WEBPACK=${2:-webpack} 8 | 9 | echo "Creating $ROLLUP and $WEBPACK branches from $REV" 10 | 11 | # create the $ROLLUP branch off the current HEAD 12 | git symbolic-ref HEAD refs/heads/$ROLLUP 13 | git reset $HEAD --hard 14 | node _template/build-pkg.js rollup 15 | git rm -r --cached .github _template package_template.json webpack.config.js 16 | git add package.json 17 | git commit -m 'Sapper template for Rollup' 18 | 19 | # create the $WEBPACK branch off the current HEAD 20 | git symbolic-ref HEAD refs/heads/$WEBPACK 21 | git reset $HEAD --hard 22 | node _template/build-pkg.js webpack 23 | git rm -r --cached .github _template package_template.json rollup.config.js 24 | git add package.json 25 | git commit -m 'Sapper template for webpack' 26 | -------------------------------------------------------------------------------- /package_template.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "TODO", 3 | "description": "TODO", 4 | "version": "0.0.1", 5 | "scripts": { 6 | "dev": "sapper dev", 7 | "build": "sapper build", 8 | "export": "sapper export", 9 | "start": "node __sapper__/build" 10 | }, 11 | "dependencies": { 12 | "compression": "^1.7.1", 13 | "polka": "next", 14 | "sirv": "^1.0.0" 15 | }, 16 | "devDependencies": { 17 | "sapper": "^0.28.0", 18 | "svelte": "^3.17.3" 19 | }, 20 | "merge-configs": { 21 | "rollup": { 22 | "scripts": { 23 | "build": "sapper build --legacy", 24 | "export": "sapper export --legacy" 25 | }, 26 | "devDependencies": { 27 | "@babel/core": "^7.0.0", 28 | "@babel/plugin-syntax-dynamic-import": "^7.0.0", 29 | "@babel/plugin-transform-runtime": "^7.0.0", 30 | "@babel/preset-env": "^7.0.0", 31 | "@babel/runtime": "^7.0.0", 32 | "@rollup/plugin-babel": "^5.0.0", 33 | "@rollup/plugin-commonjs": "^14.0.0", 34 | "@rollup/plugin-node-resolve": "^8.0.0", 35 | "@rollup/plugin-replace": "^2.4.0", 36 | "@rollup/plugin-url": "^5.0.0", 37 | "rollup": "^2.3.4", 38 | "rollup-plugin-svelte": "^7.0.0", 39 | "rollup-plugin-terser": "^7.0.0" 40 | } 41 | }, 42 | "webpack": { 43 | "devDependencies": { 44 | "file-loader": "^6.0.0", 45 | "svelte-loader": "^3.0.0", 46 | "webpack": "^4.46.0", 47 | "webpack-modules": "^1.0.0" 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import path from 'path'; 2 | import resolve from '@rollup/plugin-node-resolve'; 3 | import replace from '@rollup/plugin-replace'; 4 | import commonjs from '@rollup/plugin-commonjs'; 5 | import url from '@rollup/plugin-url'; 6 | import svelte from 'rollup-plugin-svelte'; 7 | import babel from '@rollup/plugin-babel'; 8 | import { terser } from 'rollup-plugin-terser'; 9 | import config from 'sapper/config/rollup.js'; 10 | import pkg from './package.json'; 11 | 12 | const mode = process.env.NODE_ENV; 13 | const dev = mode === 'development'; 14 | const legacy = !!process.env.SAPPER_LEGACY_BUILD; 15 | 16 | const onwarn = (warning, onwarn) => 17 | (warning.code === 'MISSING_EXPORT' && /'preload'/.test(warning.message)) || 18 | (warning.code === 'CIRCULAR_DEPENDENCY' && /[/\\]@sapper[/\\]/.test(warning.message)) || 19 | onwarn(warning); 20 | 21 | export default { 22 | client: { 23 | input: config.client.input(), 24 | output: config.client.output(), 25 | plugins: [ 26 | replace({ 27 | preventAssignment: true, 28 | values:{ 29 | 'process.browser': true, 30 | 'process.env.NODE_ENV': JSON.stringify(mode) 31 | }, 32 | }), 33 | svelte({ 34 | compilerOptions: { 35 | dev, 36 | hydratable: true 37 | } 38 | }), 39 | url({ 40 | sourceDir: path.resolve(__dirname, 'src/node_modules/images'), 41 | publicPath: '/client/' 42 | }), 43 | resolve({ 44 | browser: true, 45 | dedupe: ['svelte'] 46 | }), 47 | commonjs(), 48 | 49 | legacy && babel({ 50 | extensions: ['.js', '.mjs', '.html', '.svelte'], 51 | babelHelpers: 'runtime', 52 | exclude: ['node_modules/@babel/**'], 53 | presets: [ 54 | ['@babel/preset-env', { 55 | targets: '> 0.25%, not dead' 56 | }] 57 | ], 58 | plugins: [ 59 | '@babel/plugin-syntax-dynamic-import', 60 | ['@babel/plugin-transform-runtime', { 61 | useESModules: true 62 | }] 63 | ] 64 | }), 65 | 66 | !dev && terser({ 67 | module: true 68 | }) 69 | ], 70 | 71 | preserveEntrySignatures: false, 72 | onwarn, 73 | }, 74 | 75 | server: { 76 | input: config.server.input(), 77 | output: config.server.output(), 78 | plugins: [ 79 | replace({ 80 | preventAssignment: true, 81 | values:{ 82 | 'process.browser': false, 83 | 'process.env.NODE_ENV': JSON.stringify(mode) 84 | }, 85 | }), 86 | svelte({ 87 | compilerOptions: { 88 | dev, 89 | generate: 'ssr', 90 | hydratable: true 91 | }, 92 | emitCss: false 93 | }), 94 | url({ 95 | sourceDir: path.resolve(__dirname, 'src/node_modules/images'), 96 | publicPath: '/client/', 97 | emitFiles: false // already emitted by client build 98 | }), 99 | resolve({ 100 | dedupe: ['svelte'] 101 | }), 102 | commonjs() 103 | ], 104 | external: Object.keys(pkg.dependencies).concat(require('module').builtinModules), 105 | preserveEntrySignatures: 'strict', 106 | onwarn, 107 | }, 108 | 109 | serviceworker: { 110 | input: config.serviceworker.input(), 111 | output: config.serviceworker.output(), 112 | plugins: [ 113 | resolve(), 114 | replace({ 115 | preventAssignment: true, 116 | values:{ 117 | 'process.browser': true, 118 | 'process.env.NODE_ENV': JSON.stringify(mode) 119 | }, 120 | }), 121 | commonjs(), 122 | !dev && terser() 123 | ], 124 | preserveEntrySignatures: false, 125 | onwarn, 126 | } 127 | }; 128 | -------------------------------------------------------------------------------- /scripts/setupTypeScript.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Run this script to convert the project to TypeScript. This is only guaranteed to work 3 | * on the unmodified default template; if you have done code changes you are likely need 4 | * to touch up the generated project manually. 5 | */ 6 | 7 | // @ts-check 8 | const fs = require('fs'); 9 | const path = require('path'); 10 | const { argv } = require('process'); 11 | 12 | const projectRoot = argv[2] || path.join(__dirname, '..'); 13 | 14 | const isRollup = fs.existsSync(path.join(projectRoot, "rollup.config.js")); 15 | 16 | function warn(message) { 17 | console.warn('Warning: ' + message); 18 | } 19 | 20 | function replaceInFile(fileName, replacements) { 21 | if (fs.existsSync(fileName)) { 22 | let contents = fs.readFileSync(fileName, 'utf8'); 23 | let hadUpdates = false; 24 | 25 | replacements.forEach(([from, to]) => { 26 | const newContents = contents.replace(from, to); 27 | 28 | const isAlreadyApplied = typeof to !== 'string' || contents.includes(to); 29 | 30 | if (newContents !== contents) { 31 | contents = newContents; 32 | hadUpdates = true; 33 | } else if (!isAlreadyApplied) { 34 | warn(`Wanted to update "${from}" in ${fileName}, but did not find it.`); 35 | } 36 | }); 37 | 38 | if (hadUpdates) { 39 | fs.writeFileSync(fileName, contents); 40 | } else { 41 | console.log(`${fileName} had already been updated.`); 42 | } 43 | } else { 44 | warn(`Wanted to update ${fileName} but the file did not exist.`); 45 | } 46 | } 47 | 48 | function createFile(fileName, contents) { 49 | if (fs.existsSync(fileName)) { 50 | warn(`Wanted to create ${fileName}, but it already existed. Leaving existing file.`); 51 | } else { 52 | fs.writeFileSync(fileName, contents); 53 | } 54 | } 55 | 56 | function addDepsToPackageJson() { 57 | const pkgJSONPath = path.join(projectRoot, 'package.json'); 58 | const packageJSON = JSON.parse(fs.readFileSync(pkgJSONPath, 'utf8')); 59 | packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { 60 | ...(isRollup ? { '@rollup/plugin-typescript': '^6.0.0' } : { 'ts-loader': '^8.0.4' }), 61 | '@tsconfig/svelte': '^1.0.10', 62 | '@types/compression': '^1.7.0', 63 | '@types/node': '^14.11.1', 64 | '@types/polka': '^0.5.1', 65 | 'svelte-check': '^1.0.46', 66 | 'svelte-preprocess': '^4.3.0', 67 | tslib: '^2.0.1', 68 | typescript: '^4.0.3' 69 | }); 70 | 71 | // Add script for checking 72 | packageJSON.scripts = Object.assign(packageJSON.scripts, { 73 | validate: 'svelte-check --ignore src/node_modules/@sapper' 74 | }); 75 | 76 | // Write the package JSON 77 | fs.writeFileSync(pkgJSONPath, JSON.stringify(packageJSON, null, ' ')); 78 | } 79 | 80 | function changeJsExtensionToTs(dir) { 81 | const elements = fs.readdirSync(dir, { withFileTypes: true }); 82 | 83 | for (let i = 0; i < elements.length; i++) { 84 | if (elements[i].isDirectory()) { 85 | changeJsExtensionToTs(path.join(dir, elements[i].name)); 86 | } else if (elements[i].name.match(/^[^_]((?!json).)*js$/)) { 87 | fs.renameSync(path.join(dir, elements[i].name), path.join(dir, elements[i].name).replace('.js', '.ts')); 88 | } 89 | } 90 | } 91 | 92 | function updateSingleSvelteFile({ view, vars, contextModule }) { 93 | replaceInFile(path.join(projectRoot, 'src', `${view}.svelte`), [ 94 | [/(?:/gm, (m, attrs) => ``], 95 | ...(vars ? vars.map(({ name, type }) => [`export let ${name};`, `export let ${name}: ${type};`]) : []), 96 | ...(contextModule ? contextModule.map(({ js, ts }) => [js, ts]) : []) 97 | ]); 98 | } 99 | 100 | // Switch the *.svelte file to use TS 101 | function updateSvelteFiles() { 102 | [ 103 | { 104 | view: 'components/Nav', 105 | vars: [{ name: 'segment', type: 'string' }] 106 | }, 107 | { 108 | view: 'routes/_layout', 109 | vars: [{ name: 'segment', type: 'string' }] 110 | }, 111 | { 112 | view: 'routes/_error', 113 | vars: [ 114 | { name: 'status', type: 'number' }, 115 | { name: 'error', type: 'Error' } 116 | ] 117 | }, 118 | { 119 | view: 'routes/blog/index', 120 | vars: [{ name: 'posts', type: '{ slug: string; title: string, html: any }[]' }], 121 | contextModule: [ 122 | { 123 | js: '.then(r => r.json())', 124 | ts: '.then((r: { json: () => any; }) => r.json())' 125 | }, 126 | { 127 | js: '.then(posts => {', 128 | ts: '.then((posts: { slug: string; title: string, html: any }[]) => {' 129 | } 130 | ] 131 | }, 132 | { 133 | view: 'routes/blog/[slug]', 134 | vars: [{ name: 'post', type: '{ slug: string; title: string, html: any }' }] 135 | } 136 | ].forEach(updateSingleSvelteFile); 137 | } 138 | 139 | function updateRollupConfig() { 140 | // Edit rollup config 141 | replaceInFile(path.join(projectRoot, 'rollup.config.js'), [ 142 | // Edit imports 143 | [ 144 | /'rollup-plugin-terser';\n(?!import sveltePreprocess)/, 145 | `'rollup-plugin-terser'; 146 | import sveltePreprocess from 'svelte-preprocess'; 147 | import typescript from '@rollup/plugin-typescript'; 148 | ` 149 | ], 150 | // Edit inputs 151 | [ 152 | /(?`, `self.addEventListener('activate', (event: ExtendableEvent) =>`], 226 | [`self.addEventListener('install', event =>`, `self.addEventListener('install', (event: ExtendableEvent) =>`], 227 | [`addEventListener('fetch', event =>`, `addEventListener('fetch', (event: FetchEvent) =>`], 228 | ]); 229 | } 230 | 231 | function createTsConfig() { 232 | const tsconfig = `{ 233 | "extends": "@tsconfig/svelte/tsconfig.json", 234 | "compilerOptions": { 235 | "lib": ["DOM", "ES2017", "WebWorker"] 236 | }, 237 | "include": ["src/**/*", "src/node_modules/**/*"], 238 | "exclude": ["node_modules/*", "__sapper__/*", "static/*"] 239 | }`; 240 | 241 | createFile(path.join(projectRoot, 'tsconfig.json'), tsconfig); 242 | } 243 | 244 | // Adds the extension recommendation 245 | function configureVsCode() { 246 | const dir = path.join(projectRoot, '.vscode'); 247 | 248 | if (!fs.existsSync(dir)) { 249 | fs.mkdirSync(dir); 250 | } 251 | 252 | createFile(path.join(projectRoot, '.vscode', 'extensions.json'), `{"recommendations": ["svelte.svelte-vscode"]}`); 253 | } 254 | 255 | function deleteThisScript() { 256 | fs.unlinkSync(path.join(__filename)); 257 | 258 | // Check for Mac's DS_store file, and if it's the only one left remove it 259 | const remainingFiles = fs.readdirSync(path.join(__dirname)); 260 | if (remainingFiles.length === 1 && remainingFiles[0] === '.DS_store') { 261 | fs.unlinkSync(path.join(__dirname, '.DS_store')); 262 | } 263 | 264 | // Check if the scripts folder is empty 265 | if (fs.readdirSync(path.join(__dirname)).length === 0) { 266 | // Remove the scripts folder 267 | fs.rmdirSync(path.join(__dirname)); 268 | } 269 | } 270 | 271 | console.log(`Adding TypeScript with ${isRollup ? "Rollup" : "webpack" }...`); 272 | 273 | addDepsToPackageJson(); 274 | 275 | changeJsExtensionToTs(path.join(projectRoot, 'src')); 276 | 277 | updateSvelteFiles(); 278 | 279 | if (isRollup) { 280 | updateRollupConfig(); 281 | } else { 282 | updateWebpackConfig(); 283 | } 284 | 285 | updateServiceWorker(); 286 | 287 | createTsConfig(); 288 | 289 | configureVsCode(); 290 | 291 | // Delete this script, but not during testing 292 | if (!argv[2]) { 293 | deleteThisScript(); 294 | } 295 | 296 | console.log('Converted to TypeScript.'); 297 | 298 | if (fs.existsSync(path.join(projectRoot, 'node_modules'))) { 299 | console.log(` 300 | Next: 301 | 1. run 'npm install' again to install TypeScript dependencies 302 | 2. run 'npm run build' for the @sapper imports in your project to work 303 | `); 304 | } 305 | -------------------------------------------------------------------------------- /src/ambient.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * These declarations tell TypeScript that we allow import of images, e.g. 3 | * ``` 4 | 7 | 8 | 9 | ``` 10 | */ 11 | declare module "*.gif" { 12 | const value: string; 13 | export default value; 14 | } 15 | 16 | declare module "*.jpg" { 17 | const value: string; 18 | export default value; 19 | } 20 | 21 | declare module "*.jpeg" { 22 | const value: string; 23 | export default value; 24 | } 25 | 26 | declare module "*.png" { 27 | const value: string; 28 | export default value; 29 | } 30 | 31 | declare module "*.svg" { 32 | const value: string; 33 | export default value; 34 | } 35 | 36 | declare module "*.webp" { 37 | const value: string; 38 | export default value; 39 | } 40 | -------------------------------------------------------------------------------- /src/client.js: -------------------------------------------------------------------------------- 1 | import * as sapper from '@sapper/app'; 2 | 3 | sapper.start({ 4 | target: document.querySelector('#sapper') 5 | }); -------------------------------------------------------------------------------- /src/components/Nav.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 50 | 51 | 61 | -------------------------------------------------------------------------------- /src/node_modules/images/successkid.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sveltejs/sapper-template/20dbab45215f7ed4f865b04b6fe279620394e80f/src/node_modules/images/successkid.jpg -------------------------------------------------------------------------------- /src/routes/_error.svelte: -------------------------------------------------------------------------------- 1 | 7 | 8 | 29 | 30 | 31 | {status} 32 | 33 | 34 |

{status}

35 | 36 |

{error.message}

37 | 38 | {#if dev && error.stack} 39 |
{error.stack}
40 | {/if} 41 | -------------------------------------------------------------------------------- /src/routes/_layout.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 17 | 18 |