What are the disadvantages of Webpack?

Webpack has long been the standard for front-end code packaging, with flexible packaging configurations, extensible plug-in mechanisms, and a large number of officially available plug-ins to support different types of files. Webpack follows the dependencies between modules, including all types of files such as JavaScript, CSS, images, font files, etc., to build a dependency map, and then packs them into bundles that run in the browser.

Webpack is an excellent and powerful packaging tool, but its steep learning path and complex configuration have been criticized. More importantly, when we change the code of a file, even if it is only a small change, Webpack needs to rebuild and repackage the entire project. Especially as projects get more complex, projects get bigger, Webpack gets slower and slower, and we spend precious development time changing code — saving it — waiting for the browser page to reload — new… Is wasted in the cycle.

Back in 2014, Webpack came out, and ES Modules didn’t exist. With the popularity of Webpack, it became ingrained in our minds that project code needed a modern packaging tool to build our applications. But it wasn’t always that way. Now, with widespread support for ES Modules in modern browsers, we finally have alternatives — Vite or Snowpack.

(If the Module specification is not clear, please refer to my other article: CommonJS and ES6 Module specification principle.)

How does Snowpack work

When a file is changed, traditional JavaScript build tools such as Webpack and Parcel need to rebuild and package the entire project code, and it takes time for the browser to see the change. Snowpack doesn’t package files during development, each file is built once and then cached permanently. When a file changes, Snowpack simply rebuilds the file, so the browser updates immediately.

Of course, Snowpack also supports packing files for production builds, with Webpack and Rollup plugins officially available (the Rollup plugin is still supported as of Snowpack V3.8.2). Because Snowpack is built and processed beforehand, there is no need to provide a complex packaging configuration for the packer.

To sum up, Snowpack’s advantages are:

  1. Fast, and not slow down as the size of the project increases;
  2. Development mode is not packaged, production mode can be packaged and optimized.

Snowpack supports JSX and TS source code by default, and can integrate other tools with plug-ins: TypeScript, Babel, Vue, Svelte, PostCSS, Sass, and more.

Unbundled Development

Snowpack transfers files to the browser independently of each other during development. These files can be built using tools like Babel, TypeScript, and Sass and loaded independently into the browser. This is possible thanks to the ESM’s import and export syntax. Whenever a file is changed, Snowpack will only rebuild that file. The ability to make use of ESM for Unbundled Development brings almost instantaneous single-file builds, loading and updating in browsers in 10-25 milliseconds.

The opposite of this is the packaged development model. Almost all of today’s popular JavaScript build tools are designed for packaged development, and each change, save, and display in the browser must be repackaged with all the remaining code. This introduces additional work and complexity into the development workflow. But since the ESM is now widely supported, this approach is no longer necessary.

The unpackaged development model has several advantages over the traditional packaged development model:

  • Individual file builds are fast;
  • The build result of a single file is deterministic;
  • Single files are easier to debug.
  • Project size does not affect dev speed;
  • Separate files cache better.

The last point is crucial: each file is built independently and cached indefinitely. As long as a file hasn’t changed, it’s never built again, and the browser never needs to download it again. This is the real power of the no-package development model.

Snowpack’s Dev Server builds a file only when the browser requests it. This means that Snowpack can be launched instantaneously (in 50 milliseconds) and then slowly scaled to infinitely large projects without slowing down. In contrast, startup times of more than 30 seconds are common when building large projects with traditional module packagers.

Snowpack provides a scaffolding tool for quickly creating projects, Create Snowpack App (CSA) (Node version requires V14.17.0 and above, there is a pit: related issue), HMR enabled by default. There are also some official project creation templates for various front-end frameworks. For example, to create a React project, you can use the following template:

npx create-snowpack-app react-snowpack --template @snowpack/app-template-minimal
Copy the code

You can also enable Fast Refresh through plug-ins. Fast Refresh is a frame-specific HMR enhancement that applies single-file updates in a way that preserves component state as it changes. Fast Refresh makes development faster, especially when developing pop-up Windows and other secondary view states that normally require clicking to reopen or revisit. Fast Refresh can be automatically enabled through the following plug-ins:

  • Preact: @prefresh/snowpack
  • React: @snowpack/plugin-react-refresh
  • Svelte: @snowpack/plugin-svelte
  • Vue (HMR only): A few lines of code

The processing of node_modules

Usually we introduce an NPM package in code like this:

import xxx from 'some-package';
Copy the code

On the one hand, ‘some-package’ has no file extension and is an invalid URL that the browser can’t recognize; NPM packages, on the other hand, are usually released using the CommonJS module specification, so they cannot run directly in a browser without going through the build process. Even if the project itself is written in the browser-native ESM and can run directly in the browser, the introduction of any NPM package will revert to packaged development mode.

Here’s what Snowpack does: Instead of packaging the entire project for just one requirement, Snowpack handles dependencies separately. See how Snowpack handles it:

node_modules/react/**/*     -> http://localhost:3000/web_modules/react.js
node_modules/react-dom/**/* -> http://localhost:3000/web_modules/react-dom.js
Copy the code
  1. Snowpack scans all packages used in the project;
  2. Snowpack reads these installed dependencies from the node_modules directory;
  3. Snowpack packs each dependency into a single JS file. For example,reactreact-domIt’s going to be converted separatelyreact.jsreact-dom.js.
  4. Each processed file can be run directly in the browser and imported via the ESM import.
  5. Because these dependencies rarely change, Snowpack rarely needs to rebuild them.

Once Snowpack has built its dependencies, any NPM package can be run directly in the browser without any module packer capabilities.

<! -- This runs directly in the browser with `snowpack dev` -->
<body>
  <script type="module">
    import React from 'react';
    console.log(React);
  </script>
</body>
Copy the code

Production of packaging

Snowpack’s original idea was that you should use a packer because you want to, not because you need to. Snowpack treats packaging as an optional production environment optimization, meaning complex packaging can be bypassed entirely.

By default, snowpack Build packs the code into the build folder using the same unbundle method as the dev command, which is fine for most projects. But Snowpack also supports packaging and optimizations, such as older browser support, code compression, code segmentation, tree-shaking, dead code elimination, and other performance optimizations.

Traditional module packagers typically require a lot of configuration, but Snowpack requires only one line of plug-ins and no configuration. This is possible because Snowpack builds before it is sent to the packer, so the packer will never see source code such as JSX, TS, Svelte, Vue, etc. The wrapper plugin only needs to care about HTML, CSS, and JS.

// Bundlers plugins are pre-configured to work with Snowpack apps.
// No config required! You just need to install the plugin first.
{
  "plugins": [["@snowpack/plugin-webpack"]]
}
Copy the code

Snowpack packaging optimizations come in two ways: built-in esbuilds and plug-ins (Webpack, Rollup or whatever else you want to use)

Method 1: Build esBuild

Snowpack recently (v3.8.2 at the time of publication) released a built-in optimizer with the help of EsBuild. With this built-in optimizer, you can package, translate, and minimize your production build 10 to 100 times faster than Webpack or Rollup.

However, Esbuild is not yet ready for production, so it is currently recommended for small projects only.

// snowpack.config.mjs
// Example: Using Snowpack's built-in bundling support
export default {
  optimize: {
    bundle: true,
    minify: true,
    target: 'es2018',
  },
};
Copy the code

All supported package-optimized interfaces are as follows:

export interface OptimizeOptions { entrypoints: 'auto' | string[] | ((options: {files: string[]}) => string[]); preload: boolean; bundle: boolean; loader? : {[ext: string]: Loader}; sourcemap: boolean | 'external' | 'inline' | 'both'; splitting: boolean; treeshake: boolean; manifest: boolean; minify: boolean; target: 'es2020' | 'es2019' | 'es2018' | 'es2017'; }Copy the code

Mode 2: plug-in

Snowpack supports the following popular module packers through plug-ins

  • Webpack (Recommended!) : @snowpack/plugin-webpack
  • Rollup: snowpack-plugin-rollup-bundle

At this stage, before built-in optimization support is mature, @snowpack/plugin-webpack is recommended.

Streaming Imports

Snowpack V3.0 introduced a new feature called Streaming Imports. Snowpack can be used to manage front-end projects. It is not necessary to install imported packages, and even NPM, YARN, PNPM can be thrown away together.

It can be enabled with the following configuration:

// snowpack.config.mjs
export default {
  packageOptions: {
    source: 'remote',}};Copy the code

This configuration tells Snowpack to fetch your imports remotely from the Skypack CDN instead of building them locally.

When you enable streaming Import and run Snow Dev, the local Server will start pulling all imports remotely from https://pkg.snowpack.dev. For example, the import “preact” in your project will be similar to the import “https://pkg.snowpack.dev/preact”. Snowpack caches the returned results for future or offline use.

Snowpack’s Dev Server has already done the translation, so your source file will still contain the import “preact” statement. When you run snowpack Build, the files generated in the build directory will contain import ‘.. /_snowpack/pkg/preact.js’; .

Pkg.snowpack. dev is snowpack ESM Package CDN based on Skypack. Every NPM package is in ESM form, and any old non-ESM package will be converted to ESM by CDN.

There are several advantages over traditional “NPM install + build locally” :

  • Fast: dependency skipinstall + buildStep, load the pre-built ESM dependencies directly from the ESM CDN and the dependencies can be cached locally for offline use.
  • Security: Because ESM Packages are pre-built, there is no opportunity to run code on your machine, but only in the browser sandbox.
  • Simple: ESM Packages are managed by Snowpack, front-end projects no longer need Node.js, and you can even throw away the NPM CLI altogether if you want.
  • Doesn’t affect the final build: The Streaming imports will still be compiled and packaged into the final code with the rest of the code, just like code packaged any other way.

Json is similar to a combination of package.json and package-lock.json.