Why NutUI 2.0 Uses Webpack Instead of Rollup for Vue Component Library

This article explores the development of NutUI 2.0, a Vue component library, detailing why Webpack was chosen over Rollup, how to configure UMD builds, manage external Vue dependencies, and leverage tree‑shaking to reduce bundle size.

JD.com Experience Design Center
JD.com Experience Design Center
JD.com Experience Design Center
Why NutUI 2.0 Uses Webpack Instead of Rollup for Vue Component Library
Our team recently released NutUI 2.0, a brand‑new mobile Vue component library, and we will share our development experience in a series of articles.

As the first article of the "Vue Component Library Engineering Exploration and Practice" series, we start from the beginning.

From static pages to modern Web Apps, front‑end engineering has become increasingly complex. Large projects suffer from tangled code and collaboration difficulties, which can be solved by modularizing code into reusable components.

Splitting a large application into many small components, each focusing on a specific feature, allows the whole to function as a powerful app—much like building with blocks.

Component‑based development greatly reduces coupling, improves maintainability and development efficiency, and facilitates team collaboration and cost reduction.

The three most popular front‑end frameworks—Vue, React, and Angular—all promote component‑based development, making components a core concept.

In Vue.js, components are its most powerful feature; they extend HTML elements and enable building large Vue applications from reusable small components.

Accumulating commonly used components enables reuse across projects, significantly improving development efficiency and reducing cost.

Therefore, a front‑end team needs a component library based on a common framework.

Modularization and Build Tools

A component library is a large project that should follow modular development principles. Modules such as components, style files, and configuration files need to be bundled into a final library file, which is handled by bundlers like Rollup or Webpack. Before discussing bundlers, we review current JavaScript module systems.

JavaScript lacked a native module system until ES6 introduced modules (export/import). Prior solutions included CommonJS and AMD. ES6 modules are now the official standard, but compatibility concerns mean other systems will coexist for some time.

ES6 Module: official standard, uses export and import.

CommonJS: used by Node.js, loads modules with require and exports via module.exports or exports.

AMD: asynchronous module definition, implemented by RequireJS, defines modules with define.

Older Chinese front‑end veterans may still mention the CMD spec from SeaJS, but it is no longer maintained and not mainstream.

Now we return to Rollup and Webpack.

Rollup is a popular library bundler used by many well‑known libraries and frameworks, including Vue and React. It can directly bundle ES6 modules and introduced tree‑shaking to eliminate unused code, reducing bundle size.

Webpack is more widely known and is typically used for application bundling, but it also supports library bundling. Webpack offers code splitting, hot module replacement, and recent versions support ES6 modules, tree‑shaking, and scope hoisting, making it suitable for both apps and libraries.

Currently, Rollup’s advantage in library bundling is less pronounced, while Webpack lags behind for application bundling. Therefore, we recommend Webpack for apps and either Rollup or Webpack for libraries.

We chose Webpack for NutUI 2 because the documentation site, examples, and the library share the same project, requiring a tool that can bundle both a library and an application.

Webpack Bundling a Library

Most front‑end developers are familiar with using Webpack for applications, but bundling a component library requires specific configuration.

Although the source uses ES6 modules, the output must be compatible with AMD, CommonJS, and script‑tag usage for non‑module environments.

In Webpack, the output.libraryTarget option determines how the library is exposed. Setting it to umd enables compatibility with CommonJS, AMD, and global variables.

Thus we set output.libraryTarget to umd.

Two additional relevant options are: output.library: the name of the exposed variable or module, dependent on output.libraryTarget. output.umdNamedDefine: when output.libraryTarget is umd, setting this to true names the AMD module; otherwise it remains anonymous.

With these options, Webpack can produce a UMD‑compatible library.

<ol><li><code>output: {</code></li>
<li><code>  path: path.resolve(__dirname, '../dist/'),</code></li>
<li><code>  filename: 'nutui.js',</code></li>
<li><code>  library: 'nutui',</code></li>
<li><code>  libraryTarget: 'umd',</code></li>
<li><code>  umdNamedDefine: true,</code></li>
<li><code>}</code></li></ol>

However, the built library throws an error in Node.js: window is not defined The UMD wrapper incorrectly references window as the global object, which does not exist in Node.js.

Webpack’s output.globalObject option specifies the global object; its default is window. For UMD libraries that must run in both browsers and Node.js, it should be set to this.

<ol><li><code>output: {</code></li>
<li><code>  path: path.resolve(__dirname, '../dist/'),</code></li>
<li><code>  filename: 'nutui.js',</code></li>
<li><code>  library: 'nutui',</code></li>
<li><code>  libraryTarget: 'umd',</code></li>
<li><code>  umdNamedDefine: true,</code></li>
<li><code>  globalObject: 'this'</code></li>
<li><code>}</code></li></ol>

Setting globalObject to this replaces window with this in the UMD wrapper, eliminating the Node.js error and enabling server‑side rendering compatibility.

External Vue.js Dependency

The component library should not bundle Vue itself; it should be treated as an external dependency. Webpack’s externals configuration can achieve this. For example, to externalize jQuery: externals: { jquery: 'jQuery' } Similarly, we configure Vue as external: externals: { vue: 'vue' } This works in module environments but fails in non‑module environments because the global variable is Vue (capital V), not vue.

Webpack allows externals values to be objects, enabling different names per environment:

externals: { 
  'vue': { 
    root: 'Vue', 
    commonjs: 'vue', 
    commonjs2: 'vue', 
    amd: 'vue' 
  } 
}

Thus Vue is correctly referenced as Vue in browsers and vue in module systems.

Tree‑shaking

Tree‑shaking, first introduced by Rollup, removes unused code during bundling, reducing bundle size. It relies on static analysis of ES6 modules, which are compile‑time imports. Therefore, to benefit from tree‑shaking, the source must use ES6 module syntax and avoid transpiling them to CommonJS (e.g., via Babel).

If Babel converts ES6 modules to CommonJS, tree‑shaking becomes impossible. Modern Webpack and Rollup can process ES6 modules directly, so configure Babel with "modules": false to preserve ES6 imports.

{ 
  "presets": [ 
    ["@babel/preset-env", { "modules": false }] 
  ] 
}

Our tests show that tree‑shaking noticeably reduces the size of the full NutUI 2.0 build.

Further topics such as on‑demand loading, theme customization, internationalization, unit testing, CI, static documentation generation, and public component development will be covered in upcoming articles.

Links

[1] NutUI 2.0 website https://nutui.jd.com [2] NutUI 2.0 repository https://github.com/jdf2e/nutui

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

VuewebpackComponent LibraryTree ShakingModule Bundlingumd
JD.com Experience Design Center
Written by

JD.com Experience Design Center

Professional, creative, passionate about design. The JD.com User Experience Design Department is committed to creating better e-commerce shopping experiences.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.