├── .changeset ├── README.md ├── config.json ├── cuddly-ducks-reply.md ├── cyan-tomatoes-count.md ├── great-dryers-cross.md ├── hungry-peas-look.md ├── lazy-zoos-clean.md ├── lucky-lizards-drive.md ├── metal-roses-flash.md ├── poor-sloths-mate.md ├── popular-zebras-yell.md ├── quiet-eels-fix.md ├── rude-walls-dress.md ├── sweet-snakes-cheat.md ├── tender-lamps-boil.md ├── tiny-garlics-argue.md └── weak-trains-pay.md ├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── ci.yml │ └── release.yml ├── .gitignore ├── .husky ├── .gitignore └── pre-commit ├── .prettierignore ├── .prettierrc.json ├── CODEOWNERS ├── CODE_OF_CONDUCT.md ├── LICENCE ├── README.md ├── bors.toml ├── jsconfig.json ├── package.json ├── packages ├── async-loader │ ├── CHANGELOG.md │ ├── async.js │ ├── index.js │ ├── package.json │ └── utils.js ├── cli │ ├── CHANGELOG.md │ ├── global.d.ts │ ├── jest.config.js │ ├── package.json │ ├── src │ │ ├── commands │ │ │ ├── build.js │ │ │ ├── info.js │ │ │ └── watch.js │ │ ├── index.js │ │ ├── lib │ │ │ ├── babel-config.js │ │ │ ├── entry.js │ │ │ ├── logo.js │ │ │ └── webpack │ │ │ │ ├── critters-plugin.js │ │ │ │ ├── dummy-loader.js │ │ │ │ ├── polyfills.js │ │ │ │ ├── prerender.js │ │ │ │ ├── proxy-loader.js │ │ │ │ ├── render-html-plugin.js │ │ │ │ ├── run-webpack.js │ │ │ │ ├── transform-config.js │ │ │ │ ├── webpack-base-config.js │ │ │ │ ├── webpack-client-config.js │ │ │ │ └── webpack-server-config.js │ │ ├── resources │ │ │ ├── favicon.ico │ │ │ ├── icon.png │ │ │ ├── manifest.json │ │ │ ├── sw-debug.js │ │ │ └── template.ejs │ │ ├── symbols.js │ │ └── util.js │ ├── sw │ │ ├── constants.js │ │ ├── index.js │ │ ├── sw.js │ │ └── utils.js │ ├── tests │ │ ├── .eslintrc │ │ ├── build.test.js │ │ ├── client.test.js │ │ ├── config-formats.test.js │ │ ├── images │ │ │ └── build.js │ │ ├── info.test.js │ │ ├── lib │ │ │ ├── chrome.js │ │ │ ├── cli.js │ │ │ ├── output.js │ │ │ └── utils.js │ │ ├── server.js │ │ ├── service-worker.test.js │ │ ├── setup.js │ │ ├── subjects │ │ │ ├── css-imports │ │ │ │ ├── index.js │ │ │ │ ├── package.json │ │ │ │ ├── style.css │ │ │ │ └── styles │ │ │ │ │ ├── a.css │ │ │ │ │ ├── b.css │ │ │ │ │ └── img.jpg │ │ │ ├── css-inline │ │ │ │ ├── index.js │ │ │ │ ├── package.json │ │ │ │ └── style.css │ │ │ ├── css-modules │ │ │ │ ├── index.js │ │ │ │ ├── package.json │ │ │ │ ├── style.css │ │ │ │ └── style.module.css │ │ │ ├── css-sass │ │ │ │ ├── index.js │ │ │ │ ├── package.json │ │ │ │ ├── style.module.sass │ │ │ │ ├── style.module.scss │ │ │ │ ├── style.sass │ │ │ │ └── style.scss │ │ │ ├── css-side-effect │ │ │ │ ├── index.js │ │ │ │ ├── package.json │ │ │ │ └── style.css │ │ │ ├── custom-babelrc │ │ │ │ ├── .babelrc │ │ │ │ ├── index.js │ │ │ │ └── package.json │ │ │ ├── custom-dotenv │ │ │ │ ├── .env │ │ │ │ ├── index.js │ │ │ │ └── package.json │ │ │ ├── custom-template │ │ │ │ ├── index.js │ │ │ │ ├── package.json │ │ │ │ └── template.ejs │ │ │ ├── custom-webpack │ │ │ │ ├── index.js │ │ │ │ ├── package.json │ │ │ │ └── preact.config.js │ │ │ ├── location-patch │ │ │ │ ├── index.js │ │ │ │ └── package.json │ │ │ ├── minimal │ │ │ │ ├── index.js │ │ │ │ ├── package.json │ │ │ │ └── style.css │ │ │ ├── multiple-config-files │ │ │ │ ├── index.js │ │ │ │ ├── package.json │ │ │ │ ├── preactConfig │ │ │ │ │ ├── cjs │ │ │ │ │ │ ├── function.js │ │ │ │ │ │ └── object.js │ │ │ │ │ └── esm │ │ │ │ │ │ ├── function.js │ │ │ │ │ │ └── object.js │ │ │ │ ├── prerender-urls.json │ │ │ │ ├── prerenderUrls │ │ │ │ │ ├── cjs │ │ │ │ │ │ ├── array.js │ │ │ │ │ │ ├── function-returning-array.js │ │ │ │ │ │ ├── function-returning-stringified-array.js │ │ │ │ │ │ └── stringified-array.js │ │ │ │ │ └── esm │ │ │ │ │ │ ├── array.js │ │ │ │ │ │ ├── function-returning-array.js │ │ │ │ │ │ ├── function-returning-stringified-array.js │ │ │ │ │ │ └── stringified-array.js │ │ │ │ └── routes │ │ │ │ │ ├── home.css │ │ │ │ │ └── home.js │ │ │ ├── multiple-prerendering-with-provider │ │ │ │ ├── index.js │ │ │ │ ├── package.json │ │ │ │ ├── prerender-urls.js │ │ │ │ ├── prerender-urls.json │ │ │ │ ├── prerender-urls.promise.js │ │ │ │ ├── routes │ │ │ │ │ ├── custom-with-hook.js │ │ │ │ │ ├── custom.css │ │ │ │ │ ├── custom.js │ │ │ │ │ ├── home.css │ │ │ │ │ ├── home.js │ │ │ │ │ ├── html-safe.js │ │ │ │ │ ├── route66.css │ │ │ │ │ └── route66.js │ │ │ │ └── style.css │ │ │ ├── multiple-prerendering │ │ │ │ ├── index.js │ │ │ │ ├── package.json │ │ │ │ ├── prerender-urls.js │ │ │ │ ├── prerender-urls.json │ │ │ │ ├── prerender-urls.promise.js │ │ │ │ ├── routes │ │ │ │ │ ├── custom.css │ │ │ │ │ ├── custom.js │ │ │ │ │ ├── home.css │ │ │ │ │ ├── home.js │ │ │ │ │ ├── route66.css │ │ │ │ │ └── route66.js │ │ │ │ └── style.css │ │ │ ├── prerendering-hydration │ │ │ │ ├── index.js │ │ │ │ └── package.json │ │ │ ├── proxy │ │ │ │ ├── index.js │ │ │ │ └── package.json │ │ │ ├── public-path │ │ │ │ ├── index.js │ │ │ │ ├── package.json │ │ │ │ ├── preact.config.js │ │ │ │ └── style.css │ │ │ └── static-root │ │ │ │ ├── index.js │ │ │ │ ├── package.json │ │ │ │ └── static │ │ │ │ └── .htaccess │ │ └── watch.test.js │ └── types.d.ts ├── create-cli │ ├── README.md │ ├── package.json │ ├── src │ │ ├── commands │ │ │ ├── create.js │ │ │ └── list.js │ │ ├── index.js │ │ ├── resources │ │ │ ├── sw.js │ │ │ └── template.ejs │ │ └── util.js │ └── tests │ │ ├── .eslintrc │ │ ├── create.test.js │ │ └── images │ │ └── create.js └── prerender-data-provider │ ├── README.md │ ├── package.json │ └── src │ ├── constants.js │ ├── context.js │ ├── hook.js │ ├── index.js │ ├── render-prop.js │ └── utils.js └── yarn.lock /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/master/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@1.3.0/schema.json", 3 | "changelog": [ 4 | "@changesets/changelog-github", 5 | { "repo": "preactjs/preact-cli" } 6 | ], 7 | "commit": false, 8 | "linked": [], 9 | "access": "public", 10 | "baseBranch": "master", 11 | "updateInternalDependencies": "patch", 12 | "ignore": [] 13 | } 14 | -------------------------------------------------------------------------------- /.changeset/cuddly-ducks-reply.md: -------------------------------------------------------------------------------- 1 | --- 2 | '@preact/async-loader': major 3 | 'preact-cli': major 4 | --- 5 | 6 | Drops support for Preact v8 7 | -------------------------------------------------------------------------------- /.changeset/cyan-tomatoes-count.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'preact-cli': major 3 | --- 4 | 5 | Alters CSS Module detection to instead rely upon file names, rather than directory names. 6 | 7 | Treating all CSS files found within `routes/` and `components/` as CSS Modules was not obvious, nor did it offer an easy way to opt out (or in) without editing the Webpack config itself. 8 | 9 | This change makes is so that users can opt into CSS Modules from anywhere in their app by instead naming their CSS files according to the pattern `*.module.css`. 10 | 11 | Anyone using CSS Modules within `routes/` or `components/` will need to alter their CSS files to be `x.module.css`. If you've disabled CSS Modules in your `preact.config.js`, you can remove that bit of configuration and use file names to instead determine behavior. 12 | -------------------------------------------------------------------------------- /.changeset/great-dryers-cross.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'preact-cli': major 3 | --- 4 | 5 | Reduces the `env` parameter of `preact.config.js` to only contain 3 values: `isProd`, `isWatch`, and `isServer`. 6 | 7 | Previously, `env` contained many semi-duplicated values (`production` and `isProd`, etc) as well as values that were unlikely to be of much use to many users (what flags were set, for instance). Because of this, the signal-to-noise ratio was rather low which we didn't like. As such, we reduced `env` down to the most basic environment info: what type of build is `preact-cli` doing and for which environement? 8 | 9 | If you customize your Webpack config using a `preact.config.js`, please be aware that you may need to update which values you consume from `env`. 10 | -------------------------------------------------------------------------------- /.changeset/hungry-peas-look.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'preact-cli': major 3 | --- 4 | 5 | To increase transparency and user control over the `template.html`, `<% preact.headEnd %>` and `<% preact.bodyEnd %>` will no longer be supported; instead, users should directly adopt the EJS and keep it in their templates. 6 | 7 | In the past, these were abstracted away as they were a bit unwieldy; EJS might be unfamiliar with users and the way data was retrieved from `html-webpack-plugin` was somewhat less than elegant. However, this has much improved over the years and the abstraction only makes simple edits less than obvious, so it is no longer fulfilling it's purpose. 8 | 9 | New projects will have a `template.ejs` created in place of the old `template.html`, containing the full EJS template. For existing projects, you can copy [the default `template.ejs`](https://github.com/preactjs/preact-cli/blob/master/packages/cli/src/resources/template.ejs) into your project or adapt it as you wish. 10 | -------------------------------------------------------------------------------- /.changeset/lazy-zoos-clean.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'preact-cli': patch 3 | 'create-preact-cli': patch 4 | --- 5 | 6 | Removed `optimize-plugin`, now a single bundle will be output. 7 | -------------------------------------------------------------------------------- /.changeset/lucky-lizards-drive.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'preact-cli': major 3 | --- 4 | 5 | HMR / the `--refresh` flag is now enabled by default in dev mode. 6 | -------------------------------------------------------------------------------- /.changeset/metal-roses-flash.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'preact-cli': major 3 | --- 4 | 5 | Changes the JSX transform from 'classic' to the newer 'automatic' 6 | 7 | Users will no longer need to add `import { h } from 'preact'` in their components; it will be done automatically for them. 8 | -------------------------------------------------------------------------------- /.changeset/poor-sloths-mate.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'preact-cli': major 3 | --- 4 | 5 | Removes `--preload` flag and functionality from build command. 6 | -------------------------------------------------------------------------------- /.changeset/popular-zebras-yell.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'preact-cli': patch 3 | --- 4 | 5 | Disables hash in CSS file names for the SSR build 6 | -------------------------------------------------------------------------------- /.changeset/quiet-eels-fix.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'preact-cli': major 3 | --- 4 | 5 | Removes `--json` & `--brotli` flags from `preact build`. Also removes `--rhl` alias for `--refresh` from `preact watch`. 6 | -------------------------------------------------------------------------------- /.changeset/rude-walls-dress.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'preact-cli': major 3 | '@preact/prerender-data-provider': major 4 | --- 5 | 6 | Updates to use html-webpack-plugin v4 7 | -------------------------------------------------------------------------------- /.changeset/sweet-snakes-cheat.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'preact-cli': major 3 | --- 4 | 5 | - Upgrades to Webpack v5 6 | - Any custom configuration you do in your `preact.config.js` may need to be altered to account for this. Plugins may need replacements or different option formats. 7 | 8 | - `--esm` flag has been removed 9 | - Dual output is now enabled by default in production builds. 10 | 11 | - `.babelrc` no longer overwrites matching keys 12 | - Instead, the config will be merged in to the default. The default still takes precedence when there are conflicts, so you will still need to use your `preact.config.js` if you want to edit or remove default plugins or presets. 13 | -------------------------------------------------------------------------------- /.changeset/tender-lamps-boil.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'preact-cli': major 3 | --- 4 | 5 | Minimum supported Node version for `preact-cli` is now v14.14.0. Please upgrade if you are on an older version. 6 | 7 | `build` and `watch` commands will no longer take an optional `src` directory argument; if you want to change the source directory from the default (`./src`), please instead use the `--src` flag (i.e., `--src differentSrc`). 8 | 9 | Upon rebuild, the output directory will no longer be outright deleted; instead, it will be emptied. This has the benefit of better supporting containerized environments where specific directories are mounted. Emptying the directory, rather than deleting and recreating it, ensures a stable reference for those tools. 10 | -------------------------------------------------------------------------------- /.changeset/tiny-garlics-argue.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'preact-cli': major 3 | 'create-preact-cli': major 4 | --- 5 | 6 | Extracts project creation functionality from `preact-cli` into `create-preact-cli` 7 | 8 | Setting up new `preact-cli` projects with `npx` is slow, as all dependencies of `preact-cli` would need to be installed, even though only a handful are used for project initialization. On the other hand, suggesting global installs is less than attractive due to NPM's poor default install location (requires `sudo`) and this can get out of sync over time. 9 | 10 | By extracting project initialization into its own package, we can provide much, much faster project setup times. 11 | 12 | To setup a new project, users will use `npm init preact-cli ...` or `yarn create preact-cli ...`. 13 | 14 | Additionally, the `--yarn` flag has been removed in favour of using the yarn initializer (`yarn create`). 15 | -------------------------------------------------------------------------------- /.changeset/weak-trains-pay.md: -------------------------------------------------------------------------------- 1 | --- 2 | 'preact-cli': patch 3 | --- 4 | 5 | Fix for incorrect minification in some specific circumstances. Files should now minify slightly better too. 6 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = tab 5 | end_of_line = lf 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | 10 | [{*.json,.*rc,*.yml,*.md}] 11 | indent_style = space 12 | indent_size = 2 13 | 14 | [*.md] 15 | trim_trailing_whitespace = false 16 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | **/node_modules 2 | **/tests/output 3 | **/tests/subjects/*/preact.config.js 4 | **/*.d.ts 5 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["eslint:recommended", "prettier"], 3 | "parser": "babel-eslint", 4 | "env": { 5 | "browser": true, 6 | "node": true, 7 | "es6": true 8 | }, 9 | "plugins": ["babel", "react", "prettier"], 10 | "settings": { 11 | "react": { 12 | "pragma": "h", 13 | "version": "preact" 14 | } 15 | }, 16 | "parserOptions": { 17 | "ecmaVersion": 2018, 18 | "ecmaFeatures": { 19 | "jsx": true 20 | } 21 | }, 22 | "rules": { 23 | "no-console": 1, 24 | "no-empty": 0, 25 | "no-unused-vars": [ 26 | 2, 27 | { 28 | "argsIgnorePattern": "^_", 29 | "varsIgnorePattern": "^_" 30 | } 31 | ], 32 | "semi": 2, 33 | "keyword-spacing": 2, 34 | "require-atomic-updates": 0, 35 | "react/no-string-refs": 2, 36 | "react/no-find-dom-node": 2, 37 | "react/no-is-mounted": 2, 38 | "react/jsx-no-comment-textnodes": 2, 39 | "react/jsx-curly-spacing": 2, 40 | "react/jsx-no-undef": 2, 41 | "react/jsx-uses-react": 2, 42 | "react/jsx-uses-vars": 2 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [preactjs] 2 | open_collective: preact 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | --- 8 | 9 | **What is the current behaviour?** 10 | A clear and concise description of what the bug is. 11 | 12 | **Steps to Reproduce** 13 | Steps to reproduce the behavior: 14 | 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | 21 | 22 | **What is the expected behaviour?** 23 | A clear and concise description of what you expected to happen. 24 | 25 | **Please mention any other relevant information** 26 | Add any other context about the problem here. 27 | 28 | Please paste the results of `npx preact-cli info` here. 29 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | --- 8 | 9 | **What is the current behaviour?** 10 | A clear and concise description of what you consider to be missing or sub-optimal. 11 | 12 | **What is the motivation or use case for changing this behaviour?** 13 | A clear and concise description of how you or other users might benefit from this feature. 14 | 15 | **Describe the solution you'd like** 16 | A clear and concise description of what you want to happen. 17 | 18 | **Please mention any other relevant information.** 19 | 20 | Please paste the results of `npx preact-cli info` here. 21 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | **What kind of change does this PR introduce?** 4 | 5 | 6 | 7 | **Did you add tests for your changes?** 8 | 9 | **Summary** 10 | 11 | 12 | 13 | 14 | **Does this PR introduce a breaking change?** 15 | 16 | 17 | 18 | **Other information** 19 | 20 | Please paste the results of `preact info` here. 21 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - next 8 | pull_request: 9 | branches: 10 | - master 11 | - next 12 | 13 | jobs: 14 | test: 15 | name: Test 16 | runs-on: ubuntu-latest 17 | timeout-minutes: 10 18 | strategy: 19 | matrix: 20 | node-version: [14.x, 16.x] 21 | 22 | steps: 23 | - uses: actions/checkout@v2 24 | with: 25 | fetch-depth: 1 26 | 27 | - name: Use Node.js ${{ matrix.node-version }} 28 | uses: actions/setup-node@v1 29 | with: 30 | node-version: ${{ matrix.node-version }} 31 | 32 | - uses: dorny/paths-filter@v2 33 | id: filter 34 | with: 35 | filters: | 36 | cli: 37 | - 'packages/cli/**' 38 | 39 | - uses: actions/cache@v3 40 | id: gittar-cache 41 | with: 42 | path: ~/.gittar 43 | key: ${{ runner.os }}-gittar 44 | 45 | - name: Get yarn cache directory path 46 | id: yarn-cache-dir-path 47 | run: echo "::set-output name=dir::$(yarn cache dir)" 48 | - uses: actions/cache@v3 49 | id: yarn-cache 50 | with: 51 | path: ${{ steps.yarn-cache-dir-path.outputs.dir }} 52 | key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} 53 | restore-keys: ${{ runner.os }}-yarn- 54 | 55 | - run: yarn install --frozen-lockfile 56 | 57 | - name: test:cli 58 | if: steps.filter.outputs.cli == 'true' 59 | env: 60 | CI: true 61 | WITH_LOG: true 62 | LIGHTHOUSE_CHROMIUM_PATH: 'which google-chrome-stable' 63 | run: yarn test:cli 64 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | release: 10 | name: Release 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout Repo 14 | uses: actions/checkout@master 15 | with: 16 | # This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits 17 | fetch-depth: 0 18 | 19 | - name: Setup Node.js 14.x 20 | uses: actions/setup-node@master 21 | with: 22 | node-version: 14.x 23 | 24 | - name: Install Dependencies 25 | run: yarn 26 | 27 | - name: Create Release Pull Request or Publish to npm 28 | uses: changesets/action@master 29 | with: 30 | # This expects you to have a script called release which does a build for your packages and calls changeset publish 31 | publish: yarn release 32 | env: 33 | GITHUB_TOKEN: ${{ secrets.REPO_SCOPED_TOKEN }} 34 | NPM_TOKEN: ${{ secrets.PREACT_NPM_TOKEN }} 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | lighthouse.*/ 4 | package-lock.json 5 | **/tests/output 6 | tmp-*.json 7 | *.log 8 | *.pem 9 | 10 | .idea/ 11 | .vscode 12 | 13 | # auto generated while running tests 14 | packages/cli/size-plugin.json 15 | -------------------------------------------------------------------------------- /.husky/.gitignore: -------------------------------------------------------------------------------- 1 | _ 2 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npx --no-install lint-staged 5 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | **/node_modules 2 | **/tests/output 3 | **/package.json 4 | **/*.ejs 5 | .changeset/*.md 6 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "avoid", 3 | "trailingComma": "es5", 4 | "tabWidth": 2, 5 | "semi": true, 6 | "useTabs": true, 7 | "singleQuote": true, 8 | "endOfLine": "lf" 9 | } 10 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @preactjs/cli 2 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | - Using welcoming and inclusive language 12 | - Being respectful of differing viewpoints and experiences 13 | - Gracefully accepting constructive criticism 14 | - Focusing on what is best for the community 15 | - Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | - The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | - Trolling, insulting/derogatory comments, and personal or political attacks 21 | - Public or private harassment 22 | - Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | - Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at help@preactjs.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /LICENCE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Jason Miller 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 | -------------------------------------------------------------------------------- /bors.toml: -------------------------------------------------------------------------------- 1 | status = [ 2 | "ci", 3 | ] 4 | required_approvals = 1 5 | use_codeowners = true 6 | delete_merged_branches = true 7 | use_squash_merge = true 8 | -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "moduleResolution": "Node", 5 | "allowJs": true, 6 | "checkJs": true, 7 | "noEmit": true, 8 | "resolveJsonModule": true, 9 | "allowSyntheticDefaultImports": true, 10 | "jsx": "preserve", 11 | "jsxFactory": "preact.h", 12 | "jsxFragmentFactory": "preact.Fragment" 13 | }, 14 | "include": ["packages/**/*"] 15 | } 16 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "workspaces": [ 4 | "packages/*" 5 | ], 6 | "scripts": { 7 | "cli": "yarn workspace preact-cli", 8 | "create-cli": "yarn workspace create-preact-cli", 9 | "pretest": "yarn lint", 10 | "test": "run-p test:*", 11 | "test:cli": "yarn cli test", 12 | "test:create-cli": "yarn create-cli test", 13 | "prettier": "prettier --write **/*.{js,ts,tsx,json,css,scss,md,yml}", 14 | "lint": "eslint .", 15 | "changeset": "changeset", 16 | "release": "ncp README.md packages/cli/README.md && changeset publish && rimraf packages/cli/README.md", 17 | "prepare": "husky install" 18 | }, 19 | "lint-staged": { 20 | "*.js": [ 21 | "eslint --fix", 22 | "prettier --write" 23 | ], 24 | "*.{ts,tsx,json,css,scss,md,yml}": [ 25 | "prettier --write" 26 | ] 27 | }, 28 | "devDependencies": { 29 | "@changesets/changelog-github": "^0.4.0", 30 | "@changesets/cli": "^2.16.0", 31 | "@types/jest": "^24.9.1", 32 | "babel-eslint": "^10.0.1", 33 | "eslint": "^7.24.0", 34 | "eslint-config-prettier": "^8.2.0", 35 | "eslint-plugin-babel": "^5.3.0", 36 | "eslint-plugin-prettier": "^3.4.0", 37 | "eslint-plugin-react": "^7.23.2", 38 | "husky": "^6.0.0", 39 | "jest": "^24.9.0", 40 | "lint-staged": "^11.0.0", 41 | "ncp": "^2.0.0", 42 | "npm-run-all": "^4.1.5", 43 | "prettier": "^2.2.1", 44 | "rimraf": "^3.0.2" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /packages/async-loader/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # @preact/async-loader 2 | 3 | ## 3.0.2 4 | 5 | ### Patch Changes 6 | 7 | - [#1763](https://github.com/preactjs/preact-cli/pull/1763) [`3c371f7`](https://github.com/preactjs/preact-cli/commit/3c371f7b54859ce52091e6c11ed237d28e429c62) Thanks [@rschristian](https://github.com/rschristian)! - Fix for possible type error in `async-loader` 8 | -------------------------------------------------------------------------------- /packages/async-loader/async.js: -------------------------------------------------------------------------------- 1 | import { h, Component } from 'preact'; 2 | 3 | const PENDING = {}; 4 | 5 | // Given a VNode, finds its previous element sibling 6 | function getPreviousSibling(vnode, inner) { 7 | // in an element parent with no preceeding siblings means we're the first child 8 | if (!vnode || typeof vnode.type === 'string') return null; 9 | const parent = vnode.__; 10 | if (!parent) return; 11 | let children = parent.__k; 12 | if (children) { 13 | if (!Array.isArray(children)) children = [children]; 14 | // only search previous children 15 | let end = children.indexOf(vnode); 16 | if (end === -1) end = children.length; 17 | for (let i = end; i--; ) { 18 | const child = children[i]; 19 | const dom = child && (child.__e || getPreviousSibling(child, true)); 20 | if (dom) return dom; 21 | } 22 | } 23 | if (!inner) return getPreviousSibling(parent); 24 | } 25 | 26 | export default function async(load) { 27 | let component; 28 | 29 | function AsyncComponent() { 30 | Component.call(this); 31 | 32 | if (!component) { 33 | this.componentWillMount = () => { 34 | load(mod => { 35 | component = (mod && mod.default) || mod; 36 | this.setState({}); 37 | }); 38 | }; 39 | 40 | this.shouldComponentUpdate = () => component != null; 41 | } 42 | 43 | this.render = props => { 44 | if (component) { 45 | return h(component, props); 46 | } 47 | 48 | const prev = getPreviousSibling(this.__v); 49 | const me = 50 | (prev && prev.nextSibling) || (this.__P || this._parentDom).firstChild; 51 | 52 | if (!me) return; 53 | if (me.nodeType === 3) return me.data; 54 | return h(me.localName, { 55 | dangerouslySetInnerHTML: PENDING, 56 | }); 57 | }; 58 | } 59 | 60 | AsyncComponent.preload = load; 61 | (AsyncComponent.prototype = new Component()).constructor = AsyncComponent; 62 | 63 | return AsyncComponent; 64 | } 65 | -------------------------------------------------------------------------------- /packages/async-loader/index.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | exports.pitch = function (req) { 4 | this.cacheable && this.cacheable(); 5 | let name; 6 | let query = this.getOptions() || {}; 7 | let routeName = 8 | typeof query.name === 'function' ? query.name(this.resourcePath) : null; 9 | 10 | if (routeName !== null) { 11 | name = routeName; 12 | } else if ('name' in query) { 13 | name = query.name; 14 | } else if ('formatName' in query) { 15 | name = query.formatName(this.resourcePath); 16 | } 17 | 18 | // import Async from '${path.relative(process.cwd(), path.resolve(__dirname, 'async-component.js'))}'; 19 | return ` 20 | import Async from ${JSON.stringify( 21 | this.utils.contextify(this.context, path.resolve(__dirname, 'async.js')) 22 | )}; 23 | 24 | function load(cb) { 25 | require.ensure([], function (require) { 26 | var result = require(${JSON.stringify( 27 | this.utils.contextify(this.context, '!!' + req) 28 | )}); 29 | typeof cb === 'function' && cb(result); 30 | }${name ? ', ' + JSON.stringify(name) : ''}); 31 | } 32 | 33 | export default Async(load); 34 | `; 35 | }; 36 | -------------------------------------------------------------------------------- /packages/async-loader/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@preact/async-loader", 3 | "version": "3.0.2", 4 | "description": "Preact's async component loader for Webpack", 5 | "homepage": "https://github.com/preactjs/preact-cli", 6 | "bugs": "https://github.com/preactjs/preact-cli/issues", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/preactjs/preact-cli.git", 10 | "directory": "packages/async-loader" 11 | }, 12 | "license": "MIT", 13 | "author": "The Preact CLI Authors (https://github.com/preactjs/preact-cli/contributors)", 14 | "files": [ 15 | "*.js" 16 | ], 17 | "dependencies": { 18 | "kleur": "^4.1.4" 19 | }, 20 | "peerDependencies": { 21 | "preact": ">= 10.0.0" 22 | }, 23 | "engines": { 24 | "node": ">=8" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/async-loader/utils.js: -------------------------------------------------------------------------------- 1 | const { blue } = require('kleur'); 2 | 3 | exports.info = function (text, code) { 4 | process.stderr.write('\n' + blue('ℹ INFO: ⚛️ ') + text + '\n'); 5 | code && process.exit(code); 6 | }; 7 | -------------------------------------------------------------------------------- /packages/cli/global.d.ts: -------------------------------------------------------------------------------- 1 | declare const __webpack_public_path__: string; 2 | 3 | declare namespace jest { 4 | interface Matchers { 5 | toBeCloseInSize(receivedSize: number, expectedSize: number): R; 6 | toFindMatchingKey(receivedKey: string): R; 7 | } 8 | } 9 | 10 | // Modified from https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/shelljs/index.d.ts 11 | declare module 'shelljs' { 12 | const shell: { 13 | cd: (string) => void; 14 | exec: (string) => { stdout: string; stderr: string; code: number }; 15 | }; 16 | export = shell; 17 | } 18 | 19 | declare module '*.module.css' { 20 | const classes: { [key: string]: string }; 21 | export default classes; 22 | } 23 | declare module '*.module.sass' { 24 | const classes: { [key: string]: string }; 25 | export default classes; 26 | } 27 | declare module '*.module.scss' { 28 | const classes: { [key: string]: string }; 29 | export default classes; 30 | } 31 | -------------------------------------------------------------------------------- /packages/cli/jest.config.js: -------------------------------------------------------------------------------- 1 | /* 2 | * For a detailed explanation regarding each configuration property, visit: 3 | * https://jestjs.io/docs/configuration 4 | */ 5 | 6 | module.exports = { 7 | // All imported modules in your tests should be mocked automatically 8 | automock: false, 9 | 10 | // Stop running tests after `n` failures 11 | bail: 0, 12 | 13 | // Automatically clear mock calls and instances between every test 14 | clearMocks: true, 15 | 16 | // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader 17 | modulePathIgnorePatterns: [ 18 | '/tests/output', 19 | '/tests/subjects', 20 | ], 21 | 22 | // A list of paths to modules that run some code to configure or set up the testing framework before each test 23 | setupFilesAfterEnv: ['/tests/setup.js'], 24 | 25 | // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped 26 | testPathIgnorePatterns: [ 27 | '\\\\node_modules\\\\', 28 | '/tests/output', 29 | '/tests/subjects', 30 | ], 31 | 32 | // This option allows use of a custom test runner 33 | // testRunner: "jest-circus/runner", 34 | 35 | // TODO: Restored in #1667, remove when upgrading Jest 36 | testEnvironment: 'node', 37 | }; 38 | -------------------------------------------------------------------------------- /packages/cli/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "preact-cli", 3 | "version": "4.0.0-next.6", 4 | "description": "Start building a Preact Progressive Web App in seconds.", 5 | "keywords": [ 6 | "preact", 7 | "cli", 8 | "pwa" 9 | ], 10 | "homepage": "https://github.com/preactjs/preact-cli", 11 | "bugs": "https://github.com/preactjs/preact-cli/issues", 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/preactjs/preact-cli.git", 15 | "directory": "packages/cli" 16 | }, 17 | "license": "MIT", 18 | "author": "The Preact CLI Authors (https://github.com/preactjs/preact-cli/contributors)", 19 | "main": "src/index.js", 20 | "types": "types.d.ts", 21 | "bin": { 22 | "preact": "src/index.js" 23 | }, 24 | "files": [ 25 | "sw", 26 | "src", 27 | "babel", 28 | "types.d.ts" 29 | ], 30 | "scripts": { 31 | "pretest": "rimraf ./tests/output", 32 | "test": "jest" 33 | }, 34 | "dependencies": { 35 | "@babel/core": "^7.13.16", 36 | "@babel/plugin-proposal-decorators": "^7.13.15", 37 | "@babel/plugin-transform-object-assign": "^7.12.13", 38 | "@babel/plugin-transform-react-jsx": "^7.13.12", 39 | "@babel/preset-env": "^7.13.15", 40 | "@babel/preset-typescript": "^7.13.0", 41 | "@preact/async-loader": "^3.0.2", 42 | "@prefresh/babel-plugin": "^0.4.1", 43 | "@prefresh/webpack": "^3.2.2", 44 | "autoprefixer": "^10.4.7", 45 | "babel-loader": "^8.2.5", 46 | "babel-plugin-macros": "^3.1.0", 47 | "babel-plugin-transform-react-remove-prop-types": "^0.4.24", 48 | "browserslist": "^4.20.3", 49 | "console-clear": "^1.0.0", 50 | "copy-webpack-plugin": "^9.1.0", 51 | "critters": "^0.0.16", 52 | "css-loader": "^6.6.0", 53 | "css-minimizer-webpack-plugin": "3.4.1", 54 | "dotenv": "^16.0.0", 55 | "ejs-loader": "^0.5.0", 56 | "envinfo": "^7.8.1", 57 | "esm": "^3.2.25", 58 | "fork-ts-checker-webpack-plugin": "^7.1.1", 59 | "get-port": "^5.0.0", 60 | "html-webpack-plugin": "^5.5.0", 61 | "html-webpack-skip-assets-plugin": "1.0.3", 62 | "ip": "^1.1.8", 63 | "isomorphic-unfetch": "^3.1.0", 64 | "kleur": "^4.1.4", 65 | "mini-css-extract-plugin": "^2.5.3", 66 | "minimatch": "^3.0.3", 67 | "postcss": "^8.4.13", 68 | "postcss-load-config": "^3.1.4", 69 | "postcss-loader": "^6.2.1", 70 | "progress-bar-webpack-plugin": "^2.1.0", 71 | "promise-polyfill": "^8.2.3", 72 | "react-refresh": "0.11.0", 73 | "sade": "^1.8.1", 74 | "size-plugin": "^2.0.2", 75 | "source-map": "^0.7.4", 76 | "source-map-loader": "^1.1.1", 77 | "stack-trace": "0.0.10", 78 | "style-loader": "^3.3.1", 79 | "terser-webpack-plugin": "^5.3.0", 80 | "webpack": "^5.67.0", 81 | "webpack-bundle-analyzer": "^4.5.0", 82 | "webpack-dev-server": "^4.9.0", 83 | "webpack-merge": "^5.8.0", 84 | "webpack-remove-empty-scripts": "^0.7.2", 85 | "workbox-cacheable-response": "^6.5.3", 86 | "workbox-core": "^6.5.3", 87 | "workbox-precaching": "^6.5.3", 88 | "workbox-routing": "^6.5.3", 89 | "workbox-strategies": "^6.5.3", 90 | "workbox-webpack-plugin": "^6.5.3" 91 | }, 92 | "devDependencies": { 93 | "@types/express": "^4.17.13", 94 | "glob": "^8.0.3", 95 | "html-looks-like": "^1.0.2", 96 | "less": "^4.1.3", 97 | "less-loader": "^10.2.0", 98 | "ncp": "^2.0.0", 99 | "p-retry": "^4.5.0", 100 | "polka": "^0.5.2", 101 | "preact": "^10.11.3", 102 | "preact-render-to-string": "^5.2.6", 103 | "preact-router": "^3.0.1", 104 | "puppeteer": "^17.1.3", 105 | "rimraf": "^3.0.2", 106 | "sass": "^1.56.1", 107 | "sass-loader": "^12.4.0", 108 | "shelljs": "^0.8.5", 109 | "sirv": "^1.0.11", 110 | "stylus": "^0.59.0", 111 | "stylus-loader": "^6.2.0", 112 | "typescript": "~4.6.4" 113 | }, 114 | "peerDependencies": { 115 | "less-loader": "^10.2.0", 116 | "preact": "^10.0.0", 117 | "preact-render-to-string": "^5.0.0", 118 | "sass-loader": "^12.4.0", 119 | "stylus-loader": "^6.2.0", 120 | "typescript": "^4.6.4" 121 | }, 122 | "peerDependenciesMeta": { 123 | "less-loader": { 124 | "optional": true 125 | }, 126 | "sass-loader": { 127 | "optional": true 128 | }, 129 | "stylus-loader": { 130 | "optional": true 131 | }, 132 | "typescript": { 133 | "optional": true 134 | } 135 | }, 136 | "engines": { 137 | "node": ">=14.14.0" 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /packages/cli/src/commands/build.js: -------------------------------------------------------------------------------- 1 | const { readdir, rm } = require('fs/promises'); 2 | const { join, resolve } = require('path'); 3 | const runWebpack = require('../lib/webpack/run-webpack'); 4 | const { toBool } = require('../util'); 5 | 6 | exports.build = async function buildCommand(argv) { 7 | // add `default:true`s, `--no-*` disables 8 | argv.prerender = toBool(argv.prerender); 9 | 10 | let cwd = resolve(argv.cwd); 11 | 12 | // Empties destination directory -- useful when mounted with Docker 13 | // or similar situations where it's preferable to avoid directory deletion 14 | let dest = resolve(cwd, argv.dest); 15 | try { 16 | await Promise.all( 17 | ( 18 | await readdir(dest) 19 | ).map(item => rm(join(dest, item), { recursive: true })) 20 | ); 21 | } catch (e) { 22 | if (e.code != 'ENOENT') throw e; 23 | } 24 | 25 | // we explicitly set the path as `dotenv` otherwise uses 26 | // `process.cwd()` -- this would cause issues in environments 27 | // like mono-repos or our test suite subjects where project root 28 | // and the current directory differ. 29 | require('dotenv').config({ path: resolve(cwd, '.env') }); 30 | 31 | await runWebpack(argv, true); 32 | }; 33 | -------------------------------------------------------------------------------- /packages/cli/src/commands/info.js: -------------------------------------------------------------------------------- 1 | const envinfo = require('envinfo'); 2 | 3 | exports.info = async function infoCommand() { 4 | const info = await envinfo.run({ 5 | System: ['OS', 'CPU'], 6 | Binaries: ['Node', 'Yarn', 'npm'], 7 | Browsers: ['Chrome', 'Edge', 'Firefox', 'Safari'], 8 | npmPackages: [ 9 | 'preact', 10 | 'preact-cli', 11 | 'preact-router', 12 | 'preact-render-to-string', 13 | ], 14 | npmGlobalPackages: ['preact-cli'], 15 | }); 16 | 17 | process.stdout.write(`\nEnvironment Info:${info}\n`); 18 | }; 19 | -------------------------------------------------------------------------------- /packages/cli/src/commands/watch.js: -------------------------------------------------------------------------------- 1 | const { resolve } = require('path'); 2 | const getPort = require('get-port'); 3 | const runWebpack = require('../lib/webpack/run-webpack'); 4 | const { isPortFree, toBool, warn } = require('../util'); 5 | 6 | exports.watch = async function watchCommand(argv) { 7 | if (argv.sw) { 8 | argv.sw = toBool(argv.sw); 9 | } 10 | 11 | let cwd = resolve(argv.cwd); 12 | 13 | // we explicitly set the path as `dotenv` otherwise uses 14 | // `process.cwd()` -- this would cause issues in environments 15 | // like mono-repos or our test suite subjects where project root 16 | // and the current directory differ. 17 | require('dotenv').config({ path: resolve(cwd, '.env') }); 18 | 19 | argv.https = toBool(process.env.HTTPS || argv.https); 20 | argv.host = process.env.HOST || argv.host; 21 | if (argv.host === '0.0.0.0' && process.platform === 'win32') { 22 | argv.host = 'localhost'; 23 | } 24 | argv.port = await determinePort(argv.port); 25 | 26 | if (argv.https) { 27 | let { key, cert, cacert } = argv; 28 | if (key && cert) { 29 | argv.https = { key, cert, ca: cacert }; 30 | } else { 31 | warn('Reverting to `webpack-dev-server` internal certificate.'); 32 | } 33 | } 34 | 35 | return runWebpack(argv, false); 36 | }; 37 | 38 | const determinePort = (exports.determinePort = async function (port) { 39 | port = parseInt(port, 10); 40 | if (port) { 41 | if (!(await isPortFree(port))) { 42 | throw new Error( 43 | `Another process is already running on port ${port}. Please choose a different port.` 44 | ); 45 | } 46 | } else { 47 | port = await getPort({ port: parseInt(process.env.PORT, 10) || 8080 }); 48 | } 49 | 50 | return port; 51 | }); 52 | -------------------------------------------------------------------------------- /packages/cli/src/index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | const sade = require('sade'); 3 | const { green } = require('kleur'); 4 | const { build } = require('./commands/build'); 5 | const { info } = require('./commands/info'); 6 | const { watch } = require('./commands/watch'); 7 | const { error } = require('./util'); 8 | const pkg = require('../package.json'); 9 | const { isNodeVersionGreater } = require('./util'); 10 | 11 | const min = pkg.engines.node; 12 | if (!isNodeVersionGreater(min)) { 13 | error( 14 | `You are using Node ${process.version} but preact-cli requires Node ${min}. Please upgrade Node to continue!\n` 15 | ); 16 | } 17 | 18 | const prog = sade('preact').version(pkg.version); 19 | 20 | prog 21 | .command('build') 22 | .describe( 23 | 'Create a production build. You can disable "default: true" flags by prefixing them with --no-