Thoughts about Projen
A new generation of project generators
Introduction
Projen, an open-source project generator, was created by Elad Ben-Israel, who also built AWS CDK. It offers modern software engineering practices like linting, prettier, test runners, Github actions, and more when starting a new project.
You might assume that Projen is only compatible with CDK, just like ChatGPT. However, after reviewing their documentation, it became apparent that Projen also handles generating project files, managing dependencies, and configuring build tools. This means that developers can concentrate on writing code instead of worrying about these tasks. Projen can be used to bootstrap various projects, including React
and mvn
apps, as listed on their website. While Projen is compatible with any project, it particularly shines when used with AWS CDK. When creating a CDK project using cdk init app
you won't have all the necessary tooling at first. Projen provides these tools, letting you focus on developing infrastructure rather than setting up the project.
In this blog post, we will explore the 'battery includes' of Projen and evaluate its outcome.
What's inside?
We will have a look at bootstrapping a CDK with Typescript and Python, React with Typescript, and a blank Python project.
AWS CDK Typescript
To start with AWS CDK in Typescript, you simply run npx projen new awscdk-app-ts
👾 Project definition file was created at /Users/jolo/Development/projen-demo/.projenrc.ts
👾 Installing dependencies...
👾 install | yarn install --check-files
yarn install v1.22.19
info No lockfile found.
[1/4] 🔍 Resolving packages...
warning npm-check-updates > pacote > @npmcli/run-script > node-gyp > make-fetch-happen > cacache > @npmcli/move-file@2.0.1: This functionality has been moved to @npmcli/fs
[2/4] 🚚 Fetching packages...
[3/4] 🔗 Linking dependencies...
[4/4] 🔨 Building fresh packages...
success Saved lockfile.
✨ Done in 37.05s.
👾 Installing dependencies...
👾 install | yarn install --check-files
yarn install v1.22.19
[1/4] 🔍 Resolving packages...
[2/4] 🚚 Fetching packages...
[3/4] 🔗 Linking dependencies...
[4/4] 🔨 Building fresh packages...
success Saved lockfile.
✨ Done in 4.80s.
> projen-demo@0.0.0 eslint
> npx projen eslint
Initialized empty Git repository in /Users/jolo/Development/projen-demo/.git/
[main (root-commit) 53e6677] chore: project created with projen
22 files changed, 6925 insertions(+)
create mode 100644 .eslintrc.json
create mode 100644 .gitattributes
create mode 100644 .github/pull_request_template.md
create mode 100644 .github/workflows/build.yml
create mode 100644 .github/workflows/pull-request-lint.yml
create mode 100644 .github/workflows/upgrade.yml
create mode 100644 .gitignore
create mode 100644 .mergify.yml
create mode 100644 .npmignore
create mode 100644 .projen/deps.json
create mode 100644 .projen/files.json
create mode 100644 .projen/tasks.json
create mode 100644 .projenrc.ts
create mode 100644 LICENSE
create mode 100644 README.md
create mode 100644 cdk.json
create mode 100644 package.json
create mode 100644 src/main.ts
create mode 100644 test/main.test.ts
create mode 100644 tsconfig.dev.json
create mode 100644 tsconfig.json
create mode 100644 yarn.lock
When working with Node.js projects, you'll find that it generates certain files for linting (using ESLint), Typescript (using tsconfig.json
), testing (using Jest), and even GitHub actions for CI/CD. To configure your project, you'll need to use the .projenrc.ts
file. However, the documentation for this can be difficult to understand. Thankfully, using Typescript can help with auto-suggestions for available configuration options. If you prefer to use pnpm
over yarn
, you can run npx projen new awscdk-app-ts --package-manager PNPM
or add it to the .projenrc.ts
file, although this is not clearly explained in the documentation.
Evaluation
The CDK Typescript app that is bootstrapped contains all the necessary tools for development, including linting rules, a testing framework, Typescript configuration, and even GitHub actions for CI/CD. Although cdk init app --language typescript
only comes equipped with jest
, in my opinion, these tools are sufficient to get started.
If you prefer a different tool, such as vitest, you can disable jest by configuring it in .projenrc.ts
. However, it is important to note that packages installed via npm
must also be added to this file to avoid being overwritten. I have made the mistake of forgetting to add a package and then having it overwritten when I ran pnpm install my-npm-package
. Additionally, the documentation is very bad.
AWS CDK Python
To bootstrap your AWS CDK python, run npx projen new awscdk-app-py
.
[main (root-commit) 68e75df] chore: project created with projen
16 files changed, 434 insertions(+)
create mode 100644 .gitattributes
create mode 100644 .github/workflows/pull-request-lint.yml
create mode 100644 .gitignore
create mode 100644 .projen/deps.json
create mode 100644 .projen/files.json
create mode 100644 .projen/tasks.json
create mode 100644 .projenrc.py
create mode 100644 README.md
create mode 100644 app.py
create mode 100644 cdk.json
create mode 100644 projen_demo/__init__.py
create mode 100644 projen_demo/main.py
create mode 100644 requirements-dev.txt
create mode 100644 requirements.txt
create mode 100644 tests/__init__.py
create mode 100644 tests/test_example.py
The .projenrc.py
file is equivalent to the .projenrc.ts
file used in the Typescript app discussed earlier. The virtual environment is established through the use of .env
, although I prefer to name it .venv
. Unfortunately, I have not been able to locate an option to change the name. While pytest
is set to True
, it is not included in requirements-dev.txt
, so you will have to add it manually to the .projenrc.py
file. However, the file does include the necessary GitHub actions for CI/CD.
Evaluation
I have encountered some issues with missing linting and formatting tools like flake8 or black. Additionally, I faced difficulties while using poetry. When I added pytest
in .projenrc.py
as dev_deps
, the npx projen
did not include the dependencies in the poetry.toml
. As a result, I had to manually add pytest
, which was unexpected. It is also important to note that installing Node.js is necessary to execute npx projen
. Considering all these issues, I would not recommend using this for your Python application. If you prefer using CDK with Python, it is better to use the standard CDK-CLI and add your developer tools there. Finally, I also do not recommend using the blank Python-projen.
React Typescript
Let's see what's included in the React app, npx projen new react-ts --package-manager PNPM
.
👾 Project definition file was created at /Users/jolo/Development/projen-demo/.projenrc.ts
👾 Installing dependencies...
👾 install | pnpm i --no-frozen-lockfile
Downloading registry.npmjs.org/typescript/4.9.5: 11.6 MB/11.6 MB, done
WARN deprecated svgo@1.3.2: This SVGO version is no longer supported. Upgrade to v2.x.x.
WARN deprecated rollup-plugin-terser@7.0.2: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser
WARN deprecated stable@0.1.8: Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility
WARN deprecated sourcemap-codec@1.4.8: Please use @jridgewell/sourcemap-codec instead
WARN deprecated w3c-hr-time@1.0.2: Use your platform's native performance.now() and performance.timeOrigin.
WARN deprecated @npmcli/move-file@2.0.1: This functionality has been moved to @npmcli/fs
Packages: +1423
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Packages are hard linked from the content-addressable store to the virtual store.
Content-addressable store is at: /Users/foo/Library/pnpm/store/v3
Virtual store is at: node_modules/.pnpm
Progress: resolved 1423, reused 959, downloaded 464, added 1423, done
node_modules/.pnpm/core-js-pure@3.30.1/node_modules/core-js-pure: Running postinstall script, done in 39ms
node_modules/.pnpm/core-js@3.30.1/node_modules/core-js: Running postinstall script, done in 38ms
dependencies:
+ react 18.2.0
+ react-dom 18.2.0
+ react-scripts 5.0.1
+ web-vitals 3.3.1
devDependencies:
+ @testing-library/jest-dom 5.16.5
+ @testing-library/react 14.0.0
+ @testing-library/user-event 14.4.3
+ @types/jest 29.5.1
+ @types/node 16.18.25 (18.16.1 is available)
+ @types/react 18.2.0
+ @types/react-dom 18.2.1
+ @typescript-eslint/eslint-plugin 5.59.1
+ @typescript-eslint/parser 5.59.1
+ eslint 8.39.0
+ eslint-import-resolver-node 0.3.7
+ eslint-import-resolver-typescript 3.5.5
+ eslint-plugin-import 2.27.5
+ npm-check-updates 16.10.9
+ projen 0.71.27
+ ts-node 10.9.1
+ typescript 4.9.5 (5.0.4 is available)
The integrity of 6434 files was checked. This might have caused installation to take longer.
Done in 15.9s
👾 Installing dependencies...
👾 install | pnpm i --no-frozen-lockfile
WARN deprecated svgo@1.3.2: This SVGO version is no longer supported. Upgrade to v2.x.x.
WARN deprecated rollup-plugin-terser@7.0.2: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser
WARN deprecated stable@0.1.8: Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility
WARN deprecated @npmcli/move-file@2.0.1: This functionality has been moved to @npmcli/fs
WARN deprecated sourcemap-codec@1.4.8: Please use @jridgewell/sourcemap-codec instead
WARN deprecated w3c-hr-time@1.0.2: Use your platform's native performance.now() and performance.timeOrigin.
Already up to date
Progress: resolved 1423, reused 1423, downloaded 0, added 0, done
Done in 3.7s
> projen-demo@0.0.0 eslint
> npx projen eslint
Initialized empty Git repository in /Users/jolo/Development/projen-demo/.git/
[main (root-commit) ca3f2aa] chore: project created with projen
35 files changed, 13095 insertions(+)
create mode 100644 .eslintrc.json
create mode 100644 .gitattributes
create mode 100644 .github/pull_request_template.md
create mode 100644 .github/workflows/build.yml
create mode 100644 .github/workflows/pull-request-lint.yml
create mode 100644 .github/workflows/upgrade.yml
create mode 100644 .gitignore
create mode 100644 .mergify.yml
create mode 100644 .npmignore
create mode 100644 .npmrc
create mode 100644 .projen/deps.json
create mode 100644 .projen/files.json
create mode 100644 .projen/tasks.json
create mode 100644 .projenrc.ts
create mode 100644 LICENSE
create mode 100644 README.md
create mode 100644 package.json
create mode 100644 pnpm-lock.yaml
create mode 100644 public/favicon.ico
create mode 100644 public/index.html
create mode 100644 public/logo192.png
create mode 100644 public/logo512.png
create mode 100644 public/manifest.json
create mode 100644 public/robots.txt
create mode 100644 src/App.css
create mode 100644 src/App.test.tsx
create mode 100644 src/App.tsx
create mode 100644 src/index.css
create mode 100644 src/index.tsx
create mode 100644 src/logo.svg
create mode 100644 src/react-app-env.d.ts
create mode 100644 src/reportWebVitals.ts
create mode 100644 src/setupTests.ts
create mode 100644 tsconfig.dev.json
create mode 100644 tsconfig.json
The app includes linting with ESLint, testing with Jest and testing library, Typescript configs, and GitHub Actions for CI/CD. The setup is like the AWS CDK Typescript, which means that all the dependencies need to be placed in the .projenrc.ts
.
Evaluation
Upon inspection, I noticed that the React app uses create-react-app
and was last updated on April 12th, 2022. However, it is not mentioned in the official documentation on react.dev. Additionally, I find it inconvenient to store my dependencies within the .projenrc.ts
file. Overall, I believe that most people would choose a better alternative, such as ViteJS, instead of using projen for their React app.
Conclusion
Projen is a valuable open-source tool designed to simplify the creation and management of software projects for developers. It works exceptionally well with AWS CDK and Typescript, automating repetitive and error-prone tasks and providing an organized project structure, a testing framework, and built-in CI/CD support.
In our blog, we have showcased several project types that Projen can bootstrap, including AWS CDK with Typescript and Python, and React app. However, the entry point file .projenrc.[ts|py|js|json]
can be frustrating to work with since it requires the manual addition of all dependencies. This is not the standard way of adding dependencies for most developers, who usually copy the npm install third-party
command from a website and paste it into the terminal. Additionally, the documentation for CDK with Python or creating a React App is not very helpful.
As a tip, you could bootstrap your AWS CDK Typescript app and then delete the .projenrc.ts
- file. But then you will need to change the permissions of all the configuration files such as tsconfig.json
, basically any file which contains ~~ Generated by projen. To modify..
as they make them read-only. For the rest, use the basic CDK- CLI and customize it to your need.