📦 Watcher, bundler, and test runner for your SwiftWasm apps
The main goal of
cartonis to provide a smooth zero-config experience when developing for WebAssembly. It currently supports these features with separate commands:
The main motivation for
cartoncame after having enough struggles with webpack.js, trying to make its config file work, looking for appropriate plugins. At some point the maintainers became convinced that the required use of
webpackin SwiftWasm projects could limit the wider adoption of SwiftWasm itself. Hopefully, with
cartonyou can avoid using
cartonalso simplifies a few other things in your SwiftWasm development workflow such as toolchain and SDK installations.
cartoncan be installed with Homebrew. Make sure you have Homebrew installed and then run:
brew install swiftwasm/tap/carton
cartonis also available as a Docker image for Linux. You can pull it with this command:
docker pull ghcr.io/swiftwasm/carton:latest
If Docker images are not suitable for you, you'll have to build
cartonfrom sources on Ubuntu, and unfortunately other Linux distributions are currently not supported. Clone the repository and run
swift build -c release, the
cartonbinary will be located in the
.build/releasedirectory after that.
carton initcommand initializes a new SwiftWasm project for you (similarly to
swift package init) with multiple templates available at your choice.
carton init --template tokamakcreates a new Tokamak project, while
carton init --template basic(equivalent to
carton init) creates an empty SwiftWasm project with no dependencies. Also,
carton init list-templatesprovides a complete list of templates (with only
-pfor short). You can edit the app source code in your favorite editor and save it,
cartonwill immediately rebuild the app and reload all browser tabs that have the app open. You can also pass a
--verboseflag to keep the build process output available, otherwise stale output is cleaned up from your terminal screen by default. If you have a custom
index.htmlpage you'd like to use when serving, pass a path to it with a
carton testcommand runs your test suite in the
wasmerenvironment, or in the browser environment. You can switch between these with the
--environmentoption, passing either
defaultBrowservalues to it respectively.
carton sdkcommand and its subcommands allow you to manage installed SwiftWasm toolchains, but is rarely needed, as
carton devinstalls the recommended version of SwiftWasm automatically.
carton sdk versionslists all installed versions, and
carton sdk localprints the version specified for the current project in the
.swift-versionfile. You can however install SwiftWasm separately if needed, either by passing an archive URL to
carton sdk installdirectly, or just specifying the snapshot version, like
carton sdk install wasm-5.3-SNAPSHOT-2020-09-25-a.
carton devcan also detect existing installations of
swiftenv, so if you already have SwiftWasm installed via
swiftenv, you don't have to do anything on top of that to start using
carton bundlecommand builds your project using the
releaseconfiguration (although you can pass the
--debugflag to it to change that), and copies all required assets to the
Bundledirectory. You can then use a static file hosting (e.g. GitHub Pages) or any other server with support for static files to deploy your application. All resulting bundle files except
index.htmlare named by their content hashes to enable cache busting. As with
carton dev, a custom
index.htmlpage can be provided through the
carton packagecommand proxies its subcommands to
swift packageinvocations on the currently-installed toolchain. This may be useful in situations where you'd like to generate an Xcode project file for your app with something like
carton package generate-xcodeproj. It would be equivalent to
swift package generate-xcodeproj, but invoked with the SwiftWasm toolchain instead of the toolchain supplied by Xcode.
All of these commands and subcommands can be passed a
--helpflag that prints usage info and information about all available options.
cartonalso embeds an HTTP server for previewing your SwiftWasm app directly in a browser. The development version of the polyfill establishes a helper WebSocket connection to the server, so that it can reload development browser tabs when rebuilt binary is available. This brings the development experience closer to Xcode live previews, which you may have previously used when developing SwiftUI apps.
cartondoes not require any config files for these basic development scenarios, while some configuration may be supported in the future, for example for complex asset pipelines if needed. The only requirement is that your
Package.swiftcontains at least a single executable product, which then will be compiled for WebAssembly and served when you start
carton devin the directory where
cartonis built with Vapor, SwiftNIO, swift-tools-support-core, and OpenCombine, and supports both macOS and Linux. (Many thanks to everyone supporting and maintaining those projects!)
carton devwith the
carton devwill compile in the
debugconfiguration. Add the
--releaseflag to compile in the
As cross-compiling to WebAssembly and running apps and tests remotely is not too dissimilar to Android development, or even development on macOS for Linux through Docker,
cartoncould potentially become a generic tool for cross-platform Swift developers. I'm not developing any Android apps currently, but if there are interested Swift for Android developers, I'd be very happy to review and merge their contributions enabling that.
If this tool saved you any amount of time or money, please consider sponsoring the SwiftWasm organization. Or you can sponsor some of our maintainers directly on their personal sponsorship pages: @carson-katri, @kateinoigakukun, and @MaxDesiatov. While some of the sponsorship tiers give you priority support or even consulting time, any amount is appreciated and helps in maintaining the project.
This project uses SwiftFormat and SwiftLint to enforce formatting and coding style. We encourage you to run SwiftFormat within a local clone of the repository in whatever way works best for you either manually or automatically via an Xcode extension, build phase or git pre-commit hook etc.
To guarantee that these tools run before you commit your changes on macOS, you're encouraged to run this once to set up the pre-commit hook:
brew bundle # installs SwiftLint, SwiftFormat and pre-commit pre-commit install # installs pre-commit hook to run checks before you commit
Refer to the pre-commit documentation page for more details and installation instructions for other platforms.
SwiftFormat and SwiftLint also run on CI for every PR and thus a CI build can fail with incosistent formatting or style. We require CI builds to pass for all PRs before merging.