Expo Snack

repository·main·Indexed 19 days ago

https://github.com/expo/snack

An open-source platform for running React Native apps in the browser via dynamic bundling and compilation. It includes the snack-sdk for interacting with the Snack runtime, snack-runtime for loading Snacks within React Native apps, and standalone browser-optimized versions of Babel (snack-babel-standalone) and ESLint (snack-eslint-standalone).

Tokens
50.6K
Snippets
178
Records
218
Agent score
67%

What's inside expo-snack

  1. Overview of Expo Snack

    main

    Expo Snack is an open-source platform designed to run React Native applications directly in a web browser. It provides a dynamic environment that bundles and compiles code on the fly, allowing users to run code in either an Expo Go mobile app or a web-based player.

    Key features include:

    • Snacks: Code snippets that can be saved and shared easily.
    • Embedding: Ability to embed "live" previews into other websites, such as the official React Native documentation.
    • Dynamic Bundling: Automatic compilation and bundling of React Native code for immediate execution.
  2. Explore the snack-sdk API surface

    main

    The snack-sdk provides a comprehensive set of tools for interacting with the Snack runtime. The API is organized into Classes, Interfaces, Type Aliases, and Functions.

    Key components include:

    • Classes: The primary entry point is the Snack class.
    • Interfaces: Error handling is managed via SnackError.
    • Type Aliases: Extensive types are provided for managing the Snack state, files (SnackFile, SnackAssetFile, SnackCodeFile), dependencies (SnackDependencies, SnackDependency), and client connections (SnackConnectedClient).
    • Functions: Utility functions are available for checking feature support (isFeatureSupported), validating SDK versions (validateSDKVersion), and managing module preloading (getPreloadedModules).
  3. Features of the snack-sdk example app

    main

    The snack-sdk example application demonstrates the following capabilities:

    • Snack Management: Edit snacks, update names, descriptions, and sdk-version, and save snacks.
    • Exporting: Download snacks as .zip files.
    • Previewing: Web-preview and previewing on the Expo Go client.
    • Performance & Rendering: Debounced updates, Web-workers, and both server-side and client-side rendering using Next.js.
  4. Define Snack files using SnackCodeFile and SnackAssetFile

    main

    A Snack is composed of multiple files. You can define these using the SnackFile union type, which consists of SnackCodeFile for logic and support files, and SnackAssetFile for external resources like images or fonts.

    • SnackCodeFile: Contains a contents string representing the code (e.g., .js, .tsx, .json, .md).
    • SnackAssetFile: Contains contents which can be a string (URL), File, Blob, or FormData. If a File, Blob, or FormData is provided, it is automatically uploaded and converted into a URL.
    // Example of defining files for a Snack
    const files: SnackFiles = {
      'App.tsx': {
        type: 'CODE',
        contents: 'import React from "react";\nexport default () => <Text>Hello</Text>;'
      },
      'logo.png': {
        type: 'ASSET',
        contents: fileBlob // Automatically uploaded
      }
    };
  5. Understand the SnackState object

    main

    The SnackState represents the current status and metadata of a Snack. It is used by SnackStateListener to react to changes. Key fields include:

    • online: Whether the Snack is currently live and accepting connections.
    • connectedClients: A SnackConnectedClients collection of clients currently viewing the Snack.
    • files: The current set of files in the Snack.
    • dependencies: The resolved dependencies available in the Snack.
    • unsaved: Boolean indicating if the current code differs from the saved version.
    • url: The unique experience URL (e.g., exp://exp.host/@snack/...).
    • missingDependencies: A dictionary of dependencies required by the project but not found.
  6. Understand snack-eslint-standalone architecture and limitations

    main

    This package is a browser-optimized version of ESLint designed to run in environments like the Snack Website. Because ESLint and @babel/eslint-parser are primarily designed for Node.js, several modifications have been made:

    • Babel Parser: To resolve presets and plugins correctly in the browser, @babel/core is swapped with snack-babel-standalone/eslint.
    • React Plugin: The eslint-plugin-react version detection (which normally uses Node's fs or resolve) is patched to return a dummy version (999.999.999) to avoid bundling Node-specific dependencies.
    • Bundled Plugins: Includes eslint-plugin-react, eslint-plugin-react-hooks, and eslint-plugin-react-native.
    • Parser Version: Uses @babel/eslint-parser@7.14.2 to maintain compatibility with browser bundling constraints.
  7. How dependencies and bundling work in Snack

    main

    Before a dependency can be used in a Snack, it must be converted into a bundle consumable by the Snack runtime. This process is handled by the Snackager service.

    Bundling occurs automatically the first time a specific package and version combination is requested. Once the bundle is created, Snackager caches it and returns the cached version for subsequent requests to improve performance.

  8. Understand the purpose of snack-content

    main

    The snack-content package provides the functions and types that define the structure and contents of Snack projects.

    Important Usage Note:

    • This package is intended for internal use by snack-sdk and the Expo servers that serve Snacks.
    • Do not use this package for client-side logic such as transports or session management; those responsibilities belong to the snack-sdk package.
  9. How require.context is supported in Snack

    main

    Since Snack does not have access to a traditional bundler during execution, require.context is re-implemented using a two-step process involving Snackager (the packager) and the Snack Runtime.

    1. Transformation (Snackager): During the build phase, Snackager uses Babel to transform require.context statements into requests for a virtual-module. This converts the standard require.context signature into a path with a query parameter.
    2. Resolution (Runtime): When the app runs, the Snack Runtime recognizes these virtual module requests. It then generates the require.context result dynamically based on the files and assets currently present in the Snack project.

    This mechanism ensures that features like Expo Router work correctly by allowing the runtime to detect the ./app directory via a virtual module request and re-initialize the context whenever the underlying files or assets change.

  10. Understand snack-babel-standalone entrypoints

    main

    The package provides two distinct entrypoints to optimize bundle sizes. You should choose the one that matches your use case to avoid loading unnecessary code:

    1. snack-babel-standalone: The default entrypoint. Loads ./src/runtime.ts. Use this for runtime code transformation (e.g., in the Snack Runtime or Snack Website).
    2. snack-babel-standalone/eslint: A drop-in replacement for @babel/core. Use this specifically for @babel/eslint-parser within snack-eslint-standalone environments.