为何本身写的组件库被引用老是报错——详解webpack的library和libraryTarget

若是咱们仅仅是实现一个项目,咱们大几率不会关注到webpack output中的这两个属性。可是若是咱们是实现一个组件库,那么这两个属性就变得相当重要了。本文从本身以前遇到的一个问题提及,继而引伸出library和libraryTarget属性。

1. 故事起源

当我本身开始写第一个组件库的时候,很快我就撸好了框架的代码,而后我兴致冲冲的把个人组件库引入到个人项目中,我记得那时候我是这么写的:vue

组件库react

import Feeds from '@/components/feeds/index';
export {
  Feeds,
};

主项目webpack

import Feeds from '@/tencent/newsH5Ad';

// 一些其余代码

<Feeds data='xxx'>

而后我就收获了一个报错,Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: null。啊?难道是个人最终输出代码有问题?我检查了一下最终输出的代码,没有问题,Feed组件的代码也在里面。这个问题我查了好久,都没有答案,最后才发现是webpack打包的问题。这就涉及到了本文的主角,library和libraryTarget。web

2.

2. library和libraryTarget

咱们都知道,webpack能够将不一样的模块化方式(commonjs, AMD, CMD, ES6 Module)的代码打包。那咱们打出来的代码包其实也能够按不一样的模块化方式生成,因此:json

libraryTarget就是配置webpack打包内容的模块方式的参数
library就是webpack打包内容的名字

因此library规定了组件库返回值的名字,libraryTarget规定了返回值的编码格式。浏览器

libraryTarget的配置选项能够分为四大类:框架

2.1 按不一样的模块方式生成

也就是咱们这个问题的解决方法,因为我写的是一个React的UI组件库,因此咱们须要commonjs的模块方式。所以只须要在webpack.config.js中配置这一项便可:异步

module.exports = {
  entry: './src/index.js',
  output: {
    filename: 'index.js',
    // library: 'MyLibrary', // 模块名称
    libraryTarget: 'commonjs2', // 输出格式
  },
  // 其余代码
}

事实上,你能够选择的选项有:模块化

commonjs/commonjs2: 将你的library暴露为CommonJS模块
amd: 将你的library暴露为amd模块
umd: 将你的library暴露为全部的模块定义下均可运行的方式

其中AMD和UMD须要指定library,若是不声明组件库则不能正常运行。这是为了在浏览器上经过script标签加载时,用AMD模块方式输出的组件库能够有明确的模块名。如:jsonp

define("MyLibrary", [], function() {
  return _entry_return_; // 此模块返回值,是入口 chunk 返回的值
});

注意:commonjs和commonjs2几乎相同,只不过commonjs只包含exports,而commonjs2还包含module.exports,因此直接使用commonjs2便可。

2.2 生成为一个变量

libraryTarget的默认值是var,顾名思义,就是将组件库入口起点的返回值生成一个变量。如:

var MyLibrary = _entry_return_;

也能够选择‘assign',那样的话将默认生成和一个全局的变量。无论是var仍是assign,都须要设置library的名称,不然就会报错。

2.3 生成一个为一个对象的属性

和第二种状况差很少,只不过会把这个变量赋值给某个对象,做为它的一个属性存在。能够选择的选项有:

this: 返回值成为this的一个属性
window: 返回值成为window的一个属性
global: 返回值成为global的一个属性

例如:

this["MyLibrary"] = _entry_return_;
window["MyLibrary"] = _entry_return_;
global["MyLibrary"] = _entry_return_;

能够看到,这种状况下也必须指定library的名字。

2.4 异步生成方式

在这种状况下,libraryTarget的值为‘jsonp’,组件库入口起点的返回值,会被包裹到一个jsonp包装容器中,并配合webpack的externals使用——组件库的依赖由externals指定。如:

MyLibrary(_entry_return_);

3. 总结

本文介绍了webpack中libraray和libraryTarget的相关内容,解释了为何不设置它们时使用webpack打包出来的组件库会有问题。通常状况下,做为vue或者react组件库,libraryTarget在commonjs2,amd,umd中三者择其一便可。

参考文献

  1. webpack文档
相关文章
相关标签/搜索