A webpack plugin that use externals of CDN urls for production and local node_modules for development

Note:This only works on Webpack 4, if you're still on Webpack 3 or below please use version 1.x

CDN extension for the HTML Webpack Plugin

Enhances html-webpack-pluginfunctionality by allowing you to specify the modules you want to externalize from node_modules in development and a CDN in production.

Basically this will allow you to greatly reduce build time when developing and improve page load performance on production.


It is recommended to run webpack on node 5.x or higher

Install the plugin with npm:

npm install webpack-cdn-plugin --save-dev

or yarn

yarn add webpack-cdn-plugin --dev

Basic Usage

Require the plugin in your webpack config:

const HtmlWebpackPlugin = require('html-webpack-plugin');
const WebpackCdnPlugin = require('webpack-cdn-plugin');

Add the plugin to your webpack config:

module.exports = {
  // ...
  plugins: [
    new HtmlWebpackPlugin(),
    new WebpackCdnPlugin({
      modules: [
          name: 'vue',
          var: 'Vue',
          path: 'dist/vue.runtime.min.js'
          name: 'vue-router',
          var: 'VueRouter',
          path: 'dist/vue-router.min.js'
          name: 'vuex',
          var: 'Vuex',
          path: 'dist/vuex.min.js'
      publicPath: '/node_modules'
  // ...

This will generate an index.htmlfile with something like below:

<!DOCTYPE html>
    <meta charset="UTF-8">
    <title>Webpack App</title>
    <link href="//unpkg.com/vue@2.3.3/dist/vue.css" rel="stylesheet">
  <script type="text/javascript" src="https://unpkg.com/vue@2.5.17/dist/vue.runtime.min.js"></script>
  <script type="text/javascript" src="https://unpkg.com/vue-router@3.0.1/dist/vue-router.min.js"></script>
  <script type="text/javascript" src="https://unpkg.com/vuex@3.0.1/dist/vuex.min.js"></script>
  <script type="text/javascript" src="/assets/app.js"></script>

And u also need config in

# src/router
import Vue from 'vue'
import VueRouter from 'vue-router'

if (!window.VueRouter) Vue.use(VueRouter)
// ...
// Any lib need Vue.use() just to do so

When you set prodto false, it will output urls using publicPath, so you might need to expose it as some sort of static route.

<!DOCTYPE html>
    <meta charset="UTF-8">
    <title>Webpack App</title>
    <link href="/node_modules/vue/dist/vue.css" rel="stylesheet">
  <script type="text/javascript" src="/node_modules/vue/dist/vue.runtime.min.js"></script>
  <script type="text/javascript" src="/node_modules/vue-router/dist/vue-router.min.js"></script>
  <script type="text/javascript" src="/node_modules/vuex/dist/vuex.min.js"></script>
  <script type="text/javascript" src="/assets/app.js"></script>

You can also use your own custom html template, please refer to html-webpack-plugin.

Please see the examplefolder for a basic working example.


You can pass an object options to WebpackCdnPlugin. Allowed values are as follows:

modules:arrayor object(for multiple pages)

The available options for each module, which is part of an array. If you want inject cdn for multiple pages, you can config like this:

// ...otherConfig
new HtmlWebpackPlugin({
      title: 'title',
      cdnModule: 'vue',
      favicon: 'path/to/favicon',
      template: 'path/to/template',
      filename: 'filename',
      // other config
 new HtmlWebpackPlugin({
      title: 'title',
      cdnModule: 'react',
      favicon: 'path/to/favicon',
      template: 'path/to/template',
      filename: 'filename',
      // other config
 new WebpackCdnPlugin({
   modules: {
      'vue': [
        { name: 'vue', var: 'Vue', path: 'dist/vue.min.js' },
      'react': [
        { name: 'react', var: 'React', path: `umd/react.${process.env.NODE_ENV}.min.js` },
        { name: 'react-dom', var: 'ReactDOM', path: `umd/react-dom.${process.env.NODE_ENV}.min.js` },

The extra html-webpack-pluginoption cdnModulecorresponds to the configuration keythat you config inside the webpack-cdn-pluginmodules

  • If you do not give cdnModulethis value, the default is to take the first one
  • If you set cdnModule = false, it will not inject cdn

More detail to see #13


The name of the module you want to externalize


If the name from the CDN resource is different from npm, you can override with this i.e. momentis moment.json cdnjs


A variable that will be assigned to the module in global scope, webpack requires this. If not supplied than it will be the same as the name.


You can specify a path to the main file that will be used, this is useful when you want the minified version for example if main does not point to it.


You can alternatively specify multiple paths which will be loaded from the CDN.


If the module comes with style sheets, you can also specify it as a path.


You can alternatively specify multiple style sheets which will be loaded from the CDN.

cssOnly:boolean| false

If the module is just a css library, you can specify cssOnlyto true, it will ignore path.


Useful when you wanted to use your own build version of the library for js files


Useful when you wanted to use your own build version of the library for css files


Overrides the global prodUrl, allowing you to specify the CDN location for a specific module


Overrides the global devUrl, allowing you to specify the location for a specific module

prod:boolean| true

prodflag defaults to true, which will output uri using the CDN, when falseit will use the file from node_modulesfolder locally.

prodUrl:string| //unpkg.com/:name@:version/:path

You can specify a custom template url with the following replacement strings:

:name: The name of the module e.g. vue

:version: The version of the module e.g. 1.0.0

:path: The path to the file e.g. lib/app.min.js

A common example is you can use cdnjs e.g. //cdnjs.cloudflare.com/ajax/libs/:name/:version/:path. If not specified it will fallback to using unpkg.com.

devUrl:string| /:name/:path

Similar to prodUrl, this option overrides the default template url for when prodis false


Prefixes the assets with this string, if none is provided it will fallback to the one set globally in webpack.options.output.publicPath, note that this is always empty when prod is trueso that it makes use of the CDN location because it is a remote resource.

optimize:boolean| false

Set to trueto ignore every module not actually required in your bundle.


Allows you to specify a custom crossoriginattribute of either "anonymous"or "use-credentials", to configure the CORS requests for the element's fetched data. Visit MDNfor more information.

pathToNodeModules?: string(optional)

Path to the node_modulesfolder to "serve" packages from. This is used to determinate what version to request for packages from the CDN.

If not provided, the value returned by process.cwd()is used.


This is a pretty simple plugin and caters mostly for my needs. However, I have made it as flexible and customizable as possible.

If you happen to find any bugs, do please report it in the issuesor can help improve the codebase, pull requestsare always welcomed.



Many thanks to the following contributors:







  • 🚀webpack 4 beta — try it today!🚀

    Now that webpack is a 0CJS (Zero Configuration) outofthebox bundler, we will lay groundwork in 4.x a...

    2 年前
  • 🔥一步一步的带你走进Webpack4的世界

    前言 webpack是当下最热门的前端资源模块化管理和打包工具,它可以将许多松散的模块按照依赖和规则打包成符号生产环境部署的前端资源,还可以将按需加载的模块进行代码分割。

    3 个月前
  • (独家!)webpack 5 changelog 全文翻译

    ★ webpack 团队于北京时间 10 月 12 日凌晨发布了 版本,本文译自 。此部分主要面向非插件开发的 webpack 使用者。 ” 简要说明 此版本重点关注以下内容: ...

    7 个月前
  • 面试必备!webpack 中那些最易混淆的 5 个知识点

    前两天为了优化公司的代码打包项目,恶补了很多 webpack4 的知识。要是放在几年前让我学习 webpack 我肯定是拒绝的,之前看过 webpack 的旧文档,比我们内部项目的文档还要简陋。

    1 年前
  • 面试官:请手写一个webpack4.0配置


    2 年前
  • 随着WebPACK定义全局变量


    2 年前
  • 闲话 CDN

    开头 这篇文章通过 FCC 上海线下和成都微信的分享,整理成文字稿顺便凑一下更新,考虑到吃瓜读者们不知道都了解到啥程度,以及我科普作者的身份(自己定的),我决定从入门到放弃的介绍一下,大致涉及: ...

    2 年前
  • 错误ocurredjsplugin.3005

    Nanoselvakumar(https://stackoverflow.com/users/2217462/nano)提出了一个问题:An error has ocurredJSPlugin.300...

    2 年前
  • 配置webpack中externals来减少打包后vendor.js的体积


    2 年前
  • 配置webpack中dev.env.js、prod.env.js,解决不同命令下项目启动和打包到指定的环境

    前后端分离的项目开发中,我们有开发环境、测试环境、预生产环境和生产环境。 1、开发环境下调试接口的时候,一般都会有好几个接口地址(开发服务器上的,本地的,接口开发人员的,七七八八的接口地址),要根...

    2 年前


扫码加入 JavaScript 社区