Default starter for JavaScript
- Platform:
- Fastly Compute
- Language:
- JavaScript
- Repo:
- https://github.com/fastly/compute-starter-kit-javascript-webpack
Use this starter
Using the Fastly CLI, create a new project using this starter somewhere on your computer:
$ fastly compute init --from=https://github.com/fastly/compute-starter-kit-javascript-webpack
Or click the button below to create a GitHub repository, provision a Fastly service, and set up continuous deployment:
Features
- Contains build steps configured to bundle your application using webpack.
- Provides a starting point for
webpack.config.js
for use with Fastly Compute. - Demonstrates the use of the webpack loader
babel-loader
to transpile JSX syntax to JavaScript during bundling using Babel.
The example source code is a JSX file and holds dependencies on react
and react-dom
. It demonstrates serialization of a React component into a stream, served as a synthesized response from a Compute application.
import * as React from 'react';import * as Server from 'react-dom/server';
const Greet = () => <h1>Hello, world!</h1>;return new Response( await Server.renderToReadableStream(<Greet />), { status: 200, headers: { 'Content-Type': 'text/html', }, },);
Understanding the code
Compute applications written in JavaScript that have the standard structure and standard dependencies can be built using the tools included with the JavaScript SDK. However, if your application needs to perform advanced tasks at build time, such as replacing global modules, providing polyfills, or transforming code (such as JSX, TypeScript, or proposed JavaScript syntaxes), you can use a module bundler.
This starter kit demonstrates the use of webpack for bundling, providing a webpack.config.js
file that can be used as a starting point for configuring your application's specific bundling needs.
Webpack is included in the project as a dependency and run in a prebuild
script, configured to place its output in an intermediate location. The build
script then references those intermediate files as its input.
The webpack.config.js
file
At minimum, the configuration file should include the following (pre-configured for this project):
entry
- The entry point source file,'./src/index.jsx'
in this app.target
- Set tofalse
, as the predefined targets provided by webpack do not match the Compute platform.devtool
- Set tofalse
, as incremental builds do not make sense in the context of Compute.output.filename
- The name of the intermediate file.'index.cjs'
in this app. See package type below for details.output.chunkFormat
- Set to'commonjs'
.output.library.type
- Set to'commonjs'
. See package type below for details.externals
- Set to[ /^fastly:.*$/, ]
. Indicates to webpack thatfastly:
imports should be looked up as external imports rather than modules undernode_modules
.resolve.extensions
- Set to[]
.resolve.conditionNames
- Set to['fastly', '...']
.- If you're using
react-dom
, use['fastly', 'edge-light', '...']
.
- If you're using
export default { entry: './src/index.jsx', target: false, devtool: false, output: { filename: 'index.cjs', chunkFormat: 'commonjs', library: { type: 'commonjs', }, }, externals: [ /^fastly:.*$/, ], resolve: { extensions: [], conditionNames: [ 'fastly', 'edge-light', '...', ], },};
Using these as a starting point, you can further customize the configuration to meet your needs. For example:
- The
module
section can be used to determine how different types of modules will be treated. - Shimming and redirecting module resolution using the
plugins
orresolve
sections are useful techniques when your code relies on Node.js built-ins, proposals, or newer standards. - Refer to the webpack configuration documentation for more details.
[!TIP] See the Fastly Documentation section on module bundling for JavaScript for further hints.
The build process
The package.json
file of this application includes the following scripts:
{ "scripts": { "prebuild": "webpack", "build": "js-compute-runtime dist/index.cjs bin/main.wasm", // other scripts }}
Building the application through fastly compute build
(or indirectly by calling fastly compute serve
or fastly compute publish
) causes the following steps to run:
- The
fastly.toml
file is consulted for itsscripts.build
value, resulting innpm run build
. This instructs npm to execute thebuild
script. - Because
package.json
defines aprebuild
script, npm first runs it:webpack
runs according towebpack.config.js
, bundlingsrc/index.jsx
and its imports into a single JS file,dist/index.cjs
. - npm runs the
build
script: Thejs-compute-runtime
CLI tool (included as part of the@fastly/js-compute
package) wraps the bundled JS file into a Wasm file atbin/main.wasm
and packages it into a.tar.gz
file ready for deployment to Compute.
Transpiling JSX using webpack
The app generated by this starter kit uses the module
section to declare babel-loader
to be used when loading .js
and .jsx
files, allowing it to use Babel with the @babel/preset-react
preset to transpile JSX syntax into JavaScript files during bundling.
export default { // ... other configuration module: { rules: [
// A module rule for transpiling JSX { test: /\.jsx?$/, exclude: /node_modules/, use: { loader: 'babel-loader', options: { presets: [ [ '@babel/preset-react', { runtime: 'automatic', }, ], ], } }, },
], }, }
Package type
The starter kit's package.json
file sets "type": "module"
. This ensures .js
source files are loaded as ES modules, enabling them to use the modern import
and export
syntax to interact with other modules and packages.
However, webpack's output format is the older CommonJS module (*1). During the bundling process, code is transformed to CommonJS syntax (e.g., import
and export
are converted to require()
and module.exports =
). The starter kit is configured to create the bundled output file with a .cjs
extension, which indicates that the file is to be treated as a CommonJS module regardless of the "type"
value of the package.
(*1) - ES module output by webpack is still experimental and not fully supported.
Conditional exports
The starter kit is configured to use the condition names fastly
and edge-light
when resolving modules (resolve.conditionNames
of webpack.config.js
). These are taken into consideration during the bundling process when webpack encounters a package that defines conditional exports.
For example, the index.jsx
file in the starter kit declares an import on react-dom/server
:
import Server from 'react-dom/server';
Because the condition name edge-light
matches against one of the conditional exports listed in react-dom
's package.json
, webpack resolves the package's entry point to a version of react-dom
built for the edge.
Running the application
To create an application using this starter kit, create a new directory for your application and switch to it, and then type the following command:
npm create @fastly/compute@latest -- --from=https://github.com/fastly/compute-starter-kit-javascript-webpack
To build and run your new application in the local development environment, type the following command:
npm run start
To build and deploy your application to your Fastly account, type the following command. The first time you deploy the application, you will be prompted to create a new service in your account.
npm run deploy
By default, webpack bundles source files in 'production'
mode. When your bundle is built, the bundle file dist/index.cjs
will be minified as an optimization. To build in development mode, specify 'development'
mode by setting the NODE_ENV
environment variable when building the bundle. This can result in a more human-readable bundle, which may help with debugging.
For example:
NODE_ENV=development npm run start
The starter kit doesn't require the use of any backends. Once deployed, you will have a Fastly service running on Compute that can generate synthetic responses at the edge.
Next steps
This starter kit is configured to use additional packages to demonstrate the transpilation of JSX to JavaScript, and the use of React to render it to HTML.
If your application does not need React or JSX, you may remove this functionality using the following steps:
- Rename the
index.jsx
file toindex.js
, and remove all code that uses the JSX syntax or that refers to thereact
andreact-dom
packages. - In
webpack.config.js
, modify theentry
field from./src/index.jsx
to./src/index.js
to reflect this file name change. - In
webpack.config.js
, remove the following, which is the loader rule forbabel-loader
:{test: /\.jsx?$/,exclude: /node_modules/,use: {loader: 'babel-loader',options: {presets: [['@babel/preset-react',{runtime: 'automatic',},],],}},}, - In
webpack.config.js
, remove'edge-light'
from theresolve.conditionNames
array. - Remove the following dependencies from your application:npm uninstall babel-loader @babel/core @babel/preset-react react react-dom
You are, of course, free to keep Babel (babel-loader
and @babel/core
) and add your own module loader rules to perform other transpilations that are useful to your application, such as to use TypeScript or to utilize TC39 proposals. Babel is a large topic in itself, and the following references may be useful to you (external resources):
Babel is only one example usage of a webpack loader. Webpack and its community provide a large number of loaders to make various types of files available for loading as modules in your application. These can be mixed and matched, allowing your application to load anything it needs, including asset (json, png, txt, etc) files, CSS files, and even CoffeeScript source files. See webpack loaders for a list of loaders.
If you need to load shims or polyfills to make functionality available to your Compute application, take a look at the Shimming guide in the webpack documentation.
If you need to redirect or alter rules related to module resolution, take a look at the Module Resolution guide in the webpack documentation.
Webpack has a very large set of configuration options, but is designed in such a way that many of the defaults are sensible, so you only need to make changes that your application needs. Refer to Configuration concept guide and the Configuration reference in the webpack documentation for further details.
Next steps
Starters are a good way to bootstrap a project. For more specific use cases, and answers to common problems, try our library of code examples.