Is Webpack Packaging Too Slow? Try the Bundleless Mode

1. Introduction

Webpack was originally designed to solve issues pertaining to frontend modularization and the Node.js ecosystem. Over the past eight years, webpack has become increasingly powerful.

  • Extremely Quick Code Compilation: Only a single file needs to be processed at a time
  • The time complexity of project development and building is always O(1), enabling continuously efficient project building.
  • Simpler Debugging Experience: SourceMap is no longer a strong dependency for achieving stable single-file debugging.
  • Using the web-standard ESModule, which is future-proof and simplifies the overall architecture

2. Differences between the Bundle and Bundleless Modes from the Resource Loading Perspective

The following section uses the popular default project create-react-app as an example to show the differences between the Bundle and Bundleless modes in the loading of page rendering resources.

The Webpack-Based Bundle Mode

The ESModule-Based Bundleless Mode

Summary

The Bundle ModeThe Bundleless ModeProject StartupGo through the full packaging processStart devServerBrowser LoadingWait for the packaging to complete and load the corresponding bundleInitiate a request and map it to a local fileLocal File UpdateRepackage into a bundleRequest a single file again

3. Implementing the Bundleless Mode

Loading Modules Using ESModule

The first step for implementing the Bundleless mode is to have the browser load the corresponding modules.

Set Type=”module” to Enable ESModule

<div id="root"></div>
<script type="module">
// Enable ESModule by setting type="module" in the script tag.
import React from 'https://cdn.pika.dev/react'
import ReactDOM from 'https://cdn.pika.dev/react-dom'
ReactDOM.render('Hello World', document.getElementById('root'))
</script>

Use Import-Maps to Support Bare Import

When using the import-maps standard that has been implemented for Chrome, you can implement bare import support by running the “import React from ‘react’” statement. In the future, we can use this capability to implement online Bundleless deployment.

<div id="root"></div>
<! -- Enable chrome://flags/#enable-experimental-productivity-features -->
<script type="importmap">
{
"imports": {
"react": "https://cdn.pika.dev/react",
"react-dom": "https://cdn.pika.dev/react-dom"
}
}
</script>
<script type="module">
// Support bare import.
import React from 'react'
import ReactDOM from 'react-dom'
ReactDOM.render('Hello World!', document.getElementById('root'))
</script>
<div id="root"></div>
<! -- Directly point to the local path -->
<script type="module" src="/src/main.jsx"></script>

Loading Non-JS File Resources

While using ESModule, we have realized the dynamic loading of Javascript (JS) using the capabilities of the browser. In the project code, we will not only import JS files but also use the following code:

// main.jsx
import React from 'react'
import ReactDOM from 'react-dom'
Import'./index.css'// Import the CSS file.
import App from '. /App' //Import the JSX file.
// Use the JSX syntax.
ReactDOM.render(<App />, document.getElementById('root'))

Implementing HotModuleReplace

HotModuleReplace can be used for the modified code to take effect immediately without refreshing the page. It allows the modified code to take effect with almost zero delays once being saved in conjunction with the Bundleless mode that delivers extremely fast and effective speeds. Currently, React can only be implemented using react-hot-loader in the webpack scenario. However, this implementation is defective in certain scenarios. We also recommend migrating to react-refresh implemented by the React team, even though react-refresh has not been implemented in webpack. In the Bundleless scenario, each of our components is loaded independently, and therefore react-refresh needs to be integrated. To complete this integration, we only need to add the corresponding scripts at the beginning and end of the file when returning a response to the browser.

Optimizing Slow Page Loading Due to a Large Number of Requests

The Bundleless mode removes the need of packaging and improves the startup speed. However, for some modules with a large number of external dependencies or files, many requests are required to obtain all resources, resulting in an increased page loading time during development. For example, the “import lodash-es” command initiates a large number of requests in the browser, as shown in the following figure:

4. Practices in the Supply Chain POS Scenario

The supply chain POS business (handled by our team) can be divided into the home improvement industry for building materials and home furnishing, and the retail industry for offline stores. In the technical architecture, each domain bundle is separately developed and eventually merged into a large single page application (SPA) using the underlying SDK. Due to the complexity of the project, the daily development process involves the following pain points:

  • Secondary compilation takes a long time after a change is made.
  • Hot module replacement (HMR) capabilities are not stable, and repeated scenario construction is required during development.
  • Debugging depends on SourceMap capabilities and is occasionally fluctuant.

Debug a Single File without SourceMap

Problems in the Implementation Process and Solutions

During the implementation process, the main problems lie with the relevant modules. They do not conform to ESModule specifications and the following coding standardization issues:

  • The coding of the Less plug-in dependency on node_modules is not standardized.
  • No specification is defined for JSX file extensions.
  • No specification is defined for babel-runtime processing.

Some Modules Are Packaged without the ESModule

  • For output packages that do not contain the ESModule or are output incorrectly, different policies apply to different types of packages.
  • Internal Packages: Release new versions of packages with ESModule included by upgrading webpack-scaffold
  • External Dependencies: Upgrade modules, such as number-precision, using the issue, pull request, and other methods
  • For packages that cannot include ESModule due to historical reasons, use @ rollup/plugin-commonjs to convert them to the ESModule format

Coding of the Less Dependency on node_modules

@import '~@ali/pos-style-mixin/style/lst.less'; 
//~ Supported only in the webpack less-loader, not in the native Less plug-in
// Uniformly migrate to the following mode.
@import '@ali/pos-style-mixin/style/lst.less';
//Configure lessOptions for final packaging in the original webpack less-loader.
/*
{
loader: 'less-loader',
options: {
lessOptions: {
javascriptEnabled: true,
paths: [path.resolve(cwd, 'node_modules')],
}
}
}
*/

The Specification for JSX File Extensions

Vite compiles files based on their file extensions. In webpack, JSX, JS, and other similar files are processed by babel-loader. As a result, some files that are essentially JSX files but without the JSX extension are ignored. Vite performs esbuild compilation only on /.(tsx? |jsx)$/ files. For JS files, it skips the esbuild process. We must convert the ignored files to JSX files to correct this issue.

Processing of Babel-Runtime

After you use babel-plugin-transform-runtime, the output of packaging looks like this:

5. Feasibility of Using the Bundleless Mode for Deployment

Due to the limitations on network requests and browser parsing, the Bundle mode can still provide great benefits to large applications in terms of the loading speed. In 2018, the V8 engine also recommended using the Bundleless mode in local development and small web applications. As the browser and network performance continue to increase and the caching capabilities of ServiceWorker grow, the impact of network loading is becoming less. In scenarios where compatibility issues can be ignored, you can try to deploy code loaded through ESModule.

6. Summary

This article shares some ideas about how to implement the Bundleless architecture to improve frontend development efficiency. It also describes some implementation practices in specific business scenarios. The essence of using the Bundleless architecture is to hand the parsing job in webpack over to the browser, which minimizes code conversion and accelerates building during development. The Bundleless mode also allows better use of browser-related development tools.

Original Source:

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store