返回介绍

1. Introduction

发布于 2023-07-23 16:03:27 字数 8040 浏览 0 评论 0 收藏 0

shadow-cljs provides everything you need to compile your ClojureScript projects with a focus on simplicity and ease of use. The provided build targets abstract away most of the manual configuration so that you only have to configure the essentials for your build. Each target provides optimal defaults for each environment and get an optimized experience during development and in release builds.

1.1. High-Level Overview

shadow-cljs is composed of 2 parts:

  • The shadow-cljs Clojure library which handles all the actual work.

  • The shadow-cljs npm package which provides a convenient interface for running most of the build functionality directly from command line.

If desired you can easily integrate the shadow-cljs Clojure library into any other Clojure/JVM build tool (eg. leiningen or the Clojure CLI tools).

It is recommended to use the npm package as that provides a more optimized development experience tailored towards CLJS development.

1.2. Basic Workflow

When working with shadow-cljs you will be defining one or more builds in the shadow-cljs.edn configuration file. Each build will have a :target property which represents a configuration preset optimized for the target environment (eg. the Browser, a node.js application or a Chrome Extension).

Each build can either produce development or release output depending on the command used to trigger the compilation. The standard build commands are: compile, watch and release.

1.2.1. Development Mode

You can either compile a development build once or run a watch process which will monitor your source files and re-compile them automatically (and live-reload the code if desired).

All development builds are optimized for the developer experience with fast feedback cycles and other features like a REPL to directly interact with your running code.

A development build should never be shipped publicly since they can become quite large and may only work on the machine they were compiled on depending on the :target.

1.2.2. Release Mode

Creating a release build will strip out all the development related code and finally run the code through the Closure Compiler. This is an optimizing Compiler for JavaScript which will significantly reduce the overall size of the code.

1.3. Important Concepts

There are several important concepts that you should familiarize yourself with when using shadow-cljs. They are integral to understanding how everything fits together and how the tool works with your code.

1.3.1. The Classpath

shadow-cljs uses the Java Virtual Machine (JVM) and its "classpath" when working with files. This is a virtual filesystem composed of many classpath entries. Each entry is either

  • A local filesystem directory, managed by :source-paths entry in the configuration.

  • Or a .jar file, representing Clojure(Script) or JVM libraries. These are compressed archives containing many files (basically just a .zip file). These are added by your :dependencies.

In the Clojure(Script) everything is namespaced and each name is expected to resolve to a file. If you have a (ns demo.app) namespace the compiler expects to find a demo/app.cljs (or .cljc) on the classpath. The classpath will be searched in order until it is found. Suppose you configured the :source-paths ["src/main" "src/test"] the compiler will first look for a src/main/demo/app.cljs and then src/test/demo/app.cljs. When the file is not found on any source path the JVM will begin looking into the .jar files on the classpath. When it finds a demo/app.cljs at the root of any of the libraries that file it will be used.

ImportantWhen a filename exists multiple times on the classpath then only the first one is used. Everything on the JVM and Clojure(Script) is namespaced to avoid such conflicts. Very similar to npm where each package must have a unique name.

It is therefore recommended to be very disciplined about the names you choose and about properly namespacing everything. It may seem repetitive to always use (ns your-company.components.foo) over (ns components.foo) but it will save you from lot of headaches later on.

This is unlike npm where the package name itself is never used inside the package itself and only relative paths are used.

1.3.2. Server Mode

shadow-cljs can be started in "server" mode which is required for long-running tasks such as watch. A watch will implicitly start the server instance if it is not already running. The server will provide the Websocket endpoint that builds will connect to as well as all the other endpoints for nREPL, Socket REPL and the development HTTP servers.

When using the shadow-cljs CLI all commands will re-use a running server instance JVM instead of starting a new JVM. This is substantially faster since start-up time can be quite slow.

Once the server is running however you only have to restart it whenever your :dependencies change and everything else can be done via the REPL.

1.3.3. REPL

The REPL is at the heart of all Clojure(Script) development and every CLI command can also be used directly from the REPL as well. It is absolutely worth getting comfortable with the REPL even if the command line may seem more familiar.

1.4. About this Book

1.4.1. Work in Progress

This is a work in progress. If you find an error, please submit a PR to fix it, or an issue with details of the problem.

1.4.2. Contributing

This source for this book is hosted on Github.

1.4.3. Conventions Used

There are many examples in this book. Most things used in these should be obvious from their context, but to prevent misunderstanding it is important to know the author’s intentions.

When command-line examples are given we may include BASH comments (starting with #), and will usually include the standard user UNIX prompt of $ to indicate separation of the command from its output.

# A comment. This command lists files:
$ ls -l
shadow-cljs.edn
project.clj
...

Many of the examples are of the configuration file for the compiler. This file contains an EDN map. Where we have already discussed required options we will often elide them for clarity. In this case we’ll usually include an ellipsis to indicate "content that is required but isn’t in our current focus":

Example 1. Specify dependencies
{:dependencies [[lib "1.0"]]}
Example 2. Add source paths
{...
 :source-paths ["src"]
 ...}

This allows us to concisely include enough context to understand the nesting of the configuration of interest:

Example 3. Nested option
{...
 :builds {:build-id {...
                     :output-dir "resources/public/js"}}}

Code examples may be similarly shortened.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文