Start your own JavaScript library using webpack and ES6

VUE项目中使用THREE.js加载obj模型 想要在vue项目中使用threejs加载如obj、vtk等格式的模型,与threejs官网略相似,却有部分不同。以下概括几个不同点: js文件引入方式不同。vue中使用npm下载js文件,例如npm install three three-orbitcontrols three-obj-mtl-loader stats-js ,注意:obj加载器使用three-obj-mtl-loader而不是... 阅读详情

转载地址:http://krasimirtsonev.com/blog/article/javascript-library-starter-using-webpack-es6


Two months ago I published a starter pack for React based on webpack. Today I found out that I need almost the same thing but without the React bit. This simplifies the setup but there are still some tricky parts. So, I made a brand new repository webpack-library-starter and placed all the stuff that we need for creating a JavaScript library.

First of all, what I meant by saying “library”

My definition for library in the context of JavaScript is a piece of code that provides specific functionality. It does one thing and it is doing it well. In the ideal case should not depend on another library or framework. A good example for library is jQuery. React and Vue.js could be also considered a library.

The library should:

  • Be available for in-browser use. Understand including the library via <script> tag.
  • Be accessible through npm
  • Be compatible with ES6(ES2015) module system, commonjs and amdspecifications.

It doesn’t matter what is used for developing the library. What is important is the file that is distributed. It should match the above requirements. I prefer to see libraries written in vanilla JavaScript though. It simply makes the contribution easier.

Directory structure

I choose the following directory structure:

+-- lib
|   +-- library.js
|   +-- library.min.js
+-- src
|   +-- index.js
+-- test

Where src contains the source files and lib the final compiled version. This means that the entry point of the library is the file under lib and not src.

The starter

I really enjoy the new ES6 specification. The bad thing is that there is some significant tooling around it. Some day we’ll probably write such JavaScript without the need of transpiler but today that’s not the case. Usually we need some sort of Babel integration. Babel can convert our ES6 files to ES5 format but it is not meant to create bundles. Or in other words, if we have the following files:

+-- lib
+-- src
    +-- index.js (es6)
    +-- helpers.js (es6)

And we apply Babel we’ll get:

+-- lib
|   +-- index.js (es5)
|   +-- helpers.js (es5)
+-- src
    +-- index.js (es6)
    +-- helpers.js (es6)

Or in other words Babel do not resolve the imports/requires. So we need a bundler and as you may guess my choice for that is webpack. What I want to achieve at the end is:

+-- lib
|   +-- library.js (es5)
|   +-- library.min.js (es5)
+-- src
    +-- index.js (es6)
    +-- helpers.js (es6)

npm commands

npm provides a nice mechanism for running tasks - scripts. There should be at least three of those registered:

"scripts": {
  "build": "...",
  "dev": "...",
  "test": "..."
}
  • npm run build - this should produce a final minified version of our library
  • npm run dev - the same as build but do not minify the result and keeps working in a watching mode
  • npm run test - runs the tests

Building the development version

npm run dev should fire webpack and should produce lib/library.js file. We start from the webpack’s configuration file:

// webpack.config.js

var webpack = require('webpack');
var path = require('path');
var libraryName = 'library';
var outputFile = libraryName + '.js';

var config = {
  entry: __dirname + '/src/index.js',
  devtool: 'source-map',
  output: {
    path: __dirname + '/lib',
    filename: outputFile,
    library: libraryName,
    libraryTarget: 'umd',
    umdNamedDefine: true
  },
  module: {
    loaders: [
      {
        test: /(\.jsx|\.js)$/,
        loader: 'babel',
        exclude: /(node_modules|bower_components)/
      },
      {
        test: /(\.jsx|\.js)$/,
        loader: "eslint-loader",
        exclude: /node_modules/
      }
    ]
  },
  resolve: {
    root: path.resolve('./src'),
    extensions: ['', '.js']
  }
};

module.exports = config;

Even if you don’t have experience with webpack you may say what is this config file doing. We define the input (entry) and the output (output) of the compilation. The module property says what should be applied against every file during processing. In our case this is babel and ESLint where ESLint is a used for checking the syntax and correctness of our code.

There is one tricky part where I spent couple of ours. It’s related to library, libraryTarget and umdNamedDefine properties. First I tried without using them and the output of the library was something like this:

(function(modules) {
  var installedModules = {};

  function __webpack_require__(moduleId) {
    if(installedModules[moduleId]) return installedModules[moduleId].exports;

    var module = installedModules[moduleId] = {
      exports: {},
      id: moduleId,
      loaded: false
    };
    modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
    module.loaded = true;
    return module.exports;
  }

  __webpack_require__.m = modules;
  __webpack_require__.c = installedModules;
  __webpack_require__.p = "";

  return __webpack_require__(0);
})([
  function(module, exports) {
    // ... my code here
  }
]);

This is how every webpack compiled code looks like. It uses similar approach like browserify. There is a self-invoking function which receives all the modules used in our application. Every of them stays behind an index of the modules array. In the code above we have only one and __webpack_require__(0) effectively runs the code in our src/index.js file.

Having a bundle like this one do not fulfill all the requirements mentioned in the beginning of this article because we do not export anything. The file is meant to be dropped in a web page. However, adding library, libraryTargetand umdNamedDefine makes webpack injecting a really nice snippet at the top:

(function webpackUniversalModuleDefinition(root, factory) {
  if(typeof exports === 'object' && typeof module === 'object')
    module.exports = factory();
  else if(typeof define === 'function' && define.amd)
    define("library", [], factory);
  else if(typeof exports === 'object')
    exports["library"] = factory();
  else
    root["library"] = factory();
})(this, function() {
return (function(modules) {
 ...
 ...

Setting libraryTarget to umd means using universal module definition for the final result. And indeed, this piece of code recognizes the environment and provides a proper bootstrapping mechanism for our library.

Building production version

The only one difference between development and production mode for webpack is the minification. Running npm run build should produce a minified version - library.min.js. webpack has a nice build-in plugin for that:

// webpack.config.js

...
var UglifyJsPlugin = webpack.optimize.UglifyJsPlugin;
var env = process.env.WEBPACK_ENV;

var libraryName = 'library';
var plugins = [], outputFile;

if (env === 'build') {
  plugins.push(new UglifyJsPlugin({ minimize: true }));
  outputFile = libraryName + '.min.js';
} else {
  outputFile = libraryName + '.js';
}

var config = {
  entry: __dirname + '/src/index.js',
  devtool: 'source-map',
  output: { ... },
  module: { ... },
  resolve: { ... },
  plugins: plugins
};

module.exports = config;

UglifyJsPlugin does the job if we add it to the plugins array. There is something else that we have to clarify. We need some conditional logic where we instruct webpack what kind of bundle to produce (production or development). One of the popular approaches is to define an environment variable and pass it from the command line. For example:

// package.json

"scripts": {
  "build": "WEBPACK_ENV=build webpack",
  "dev": "WEBPACK_ENV=dev webpack --progress --colors --watch"
}

(Notice the --watch option. It makes webpack continuously running and watching for changes)

Testing

I’m usually using Mocha and Chai for testing and that’s what I added in the starter. Again there was a tricky part making Mocha understands ES6 files but thankfully to Babel the problem was resolved.

// package.json
"scripts": {
  ...
  "test": "mocha --compilers js:babel-core/register --colors -w ./test/*.spec.js"
}

The important bit is the --compilers option. It allows us to process the incoming file before running it.

A few other configuration files

Babel received some major changes in the newest version 6. We now have something called presets where we describe what kind of transformation we want. One of the easiest ways to configure that is with a .babelrc file:

// .babelrc
{
  "presets": ["es2015"],
  "plugins": ["babel-plugin-add-module-exports"]
}

ESLint provides the same thing and we have .eslintrc:

// .eslintrc
{
  "ecmaFeatures": {
    "globalReturn": true,
    "jsx": true,
    "modules": true
  },
  "env": {
    "browser": true,
    "es6": true,
    "node": true
  },
  "globals": {
    "document": false,
    "escape": false,
    "navigator": false,
    "unescape": false,
    "window": false,
    "describe": true,
    "before": true,
    "it": true,
    "expect": true,
    "sinon": true
  },
  "parser": "babel-eslint",
  "plugins": [],
  "rules": {
    // ... lots of lots of rules here
  }
}

The starter is available in GitHub here github.com/krasimir/webpack-library-starter.

Used tools:

Dependencies:

// package.json
"devDependencies": {
  "babel": "6.3.13",
  "babel-core": "6.1.18",
  "babel-eslint": "4.1.3",
  "babel-loader": "6.1.0",
  "babel-plugin-add-module-exports": "0.1.2",
  "babel-preset-es2015": "6.3.13",
  "chai": "3.4.1",
  "eslint": "1.7.2",
  "eslint-loader": "1.1.0",
  "mocha": "2.3.4",
  "webpack": "1.12.9"
}


Webpack 实践: 前端 SDK 开发(使用 webpack 打包 library) Webpack 实践: 前端 SDK 开发(使用 webpack 打包 library) 文章目录Webpack 实践: 前端 SDK 开发(使用 webpack 打包 library)前言正文1. 第一版:源代码直接导出1.1 目录结构 & 源代码1.2 package.json 配置1.3 创建本地软连接1.4 引入结果测试2. 第二版:使用 webpack 打包2.1 安装依赖 & 目录结构2.2 源代码扩展2.3 webpack.config.js 配置2.4 打包成果2.5 usa 阅读详情

相关推荐

webpack_es6_library_starter:轻量级入门包,用于创建JavaScript库

用于创建库的javascript入门包 为什么是另一个入门者 对于任何新应用,从create-react-app开始非常容易。 不幸的是,它不支持创建库。 有一些极富挑战性的启动程序,但是没有任何通用的启动器占用很小的空间。 使用的图书馆 所有使用的库都是devDependencies,以简化开发过程,但它们不会影响组件的占用空间。 用于操场的webpack开发服务器 建筑的通天塔 热模块更换 埃斯林特 流 笑话 如何使用它 git clone https://github.com/adamgajzlerowicz/webpack_es6_library_starter.git my-component yarn yarn start 可用命令 毛绒#带有--fix的毛毯 纱线测试#开玩笑 纱线开始#运行playgrond 纱线构建#将src转换为lib并复制流src 纱线流#运行流

Clawpatch源码解析:Provider适配器模式与Zod证据校验的TypeScript实现

Clawpatch 是一款自动代码审查工具,它把仓库切成语义化的功能切片,调用本地已安装的 coding agent 逐一审查,并保存带证据的 findings(审查发现)供后续修复。它的两个核心设计值得源码级学习:**Provider 适配器模式**——用统一接口屏蔽 Codex、Claude Code、Grok 等 9 种 agent CLI 的差异;**Zod 证据校验**——用 Zod s

gitblog_00011的博客 401

webpack-library-starter, web service生成库的样板( 输入.zip

webpack-library-starter, web service生成库的样板( 输入 web pack库启动器web pack生成库的样板样板( 输入: ES6,输出:通用库) 特性web pack 3基于。ES6作为源。以格式导出,使你的库随处工作。使用 mocha 和 chain测试设置。带有 ES

29.webpack——library与libraryTarget的用法/如何打包一个库文件

【重学webpack系列——webpack5.0】 1-15节主要讲webpack的使用,当然,建议结合《webpack学完这些就够了》一起学习。 从第16节开始,专攻webpack原理和高级API,只有深入原理和高级API,才能学到webpack设计的精髓,从而将技术点运用到实际项目中。 可以点击上方专栏订阅哦。 以下是本节正文: commonjs与commonjs2的区别 // commonjs exports.add = function(a, b){ return a + b; }

2024路在何方 2160

js-library-starter-kit:适用于开源项目JavaScript库入门工具包

JS开源入门工具包 JS入门套件说明 克隆repo git clone REPO_LINK 使用您的库名称在项目文件夹“ LIBRARY_NAME进行全局查找/替换 观看以及 利润 安装 该软件包通过npm分发: npm install LIBRARY_NAME 用法 /* Your code examples here */ 历史 待办事项:写入历史记录 执照 待办事项:写许可证 贡献者名单 戴维·威尔斯 学分,灵感,替代方法 非常感谢Kent C. Dodds关于此问题的[ https://egghead.io/lessons/javascript-how-to-write-a-javascript-library-introduction](Egghead.io系列)。

webpack-library-starter:用于生成库的基于Webpack的样板(输入:ES6,输出:通用库)

Webpack库启动器 用于生成库的基于Webpack的样板(输入:ES6 / TypeScript,输出:通用库) 特征 基于Webpack 5。 ES6或TypeScript作为源。 以格式导出,因此您的库可在任何地方使用。 用测试设置。 过程 ES6/TypeScript source files | | webpack | +--- babel | ready to use library in umd format 请记住,发布之前必须先构建库。 lib文件夹下的文件是应分发的文件。 入门 设置图书馆名称 打开webpack.config.js文件并更改libraryName变量的值。 打开package.json文件并更改main属性的值,使其与您的库的名称匹配。 建立你的

webpack的模块打包

webpack以模块方式导出的配置 module.exports = { entry: 'XX', mode: 'development', devtool: 'cheap-module', output: { filename: 'XX', path: 'XXX', library: 'MyLibrary', ...

chenyHahaha的博客 646

从网口变压器到TVS管:手把手设计通过4KV浪涌的以太网电路

本文详细解析工业级以太网接口4KV浪涌防护设计,从网口变压器选型到TVS管布局,提供通过IEC61000-4-5标准测试的完整方案。重点介绍Bob Smith电路优化和PCB设计技巧,帮助工程师有效应对雷电感应和设备开关瞬态干扰,确保工业设备稳定运行。

study的专栏 286

webpack 加载第三方js库(这里以jquery为例)

当webpack使用第三方库的时候 可以使用 webpack.providePlugin插件 有三种方式 1. 直接在html文件中引入 cdn上的文件  (注意这种方式是引用网络上的 CDN 文件) &lt;script src="http://code.jquery.com/jquery-migrate-1.2.1.min.js"&gt;&lt;/script&gt;.js 在ht...

hjh15827475896的博客 3525

反无人机技术实战解析:从探测到拦截的全方位防御策略

本文深入解析了反无人机(C-UAS)技术的全链条防御策略。从雷达、无线电频谱、光电等多维度探测技术,到数据融合与威胁评估,再到无线电干扰、导航诱骗及物理拦截等核心拦截手段,系统阐述了如何构建从探测到拦截的实战化防御体系,为关键设施、大型活动等场景提供定制化空域安全解决方案。

weixin_29230649的博客 403

华为昇腾310P3+deepseek蒸馏版性能调优:FP16精度优化全记录

本文详细介绍了在华为昇腾310P3硬件环境下优化DeepSeek蒸馏版模型FP16精度的关键技术路径。通过分层量化策略、内存分配优化和并行计算配置,显著提升模型推理性能,实现83%的并发处理能力提升,同时保持98.7%的原始模型准确率。

weixin_29074409的博客 350

webpack config output libraryTarget

libraryTarget: “var”(default) output.library 会将值作为变量声明导出(当使用 script 标签时,其执行后在全局作用域可用)。 libraryTarget: “window” 当 library 加载完成,入口起点的返回值将分配给 window 对象。 libraryTarget: “assign” libraryTarget: “this” libr...

like419的博客 1648

光模块的封装工艺有哪些?

COB封装传统的单路10Gb/s或25Gb/s速率的光模块采用SFP封装将电芯片和TO封装的光收发组件焊接到PCB板上组成光模块。但对于40G及以上速率的高速光模块,受激光器速率限制(多为25G),主要通过多通道并行实现,如40G由4×10G实现,而100G则由4×25G实现。蝶形封装:壳体通常为长方体,结构及实现功能通常比较复杂,可以内置制冷器、热沉、陶瓷基块、芯片、热敏电阻、背光监控,并且可以支持所有以上部件的键合引线。BOX封装属于蝶形封装的一种,用于多通道并行封装。

WaytoICT- Explore ICT Technology, Build Your Tech Path 3810

webpack打包你的es6模块工具库

1.package.json添加webpack { "name": "my-utils", "version": "1.0.0", "description": "打包一个es6模块化的工具库", "author": "your name", "main": "./src/index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build": "we

qq575792372的博客 1263

傻瓜式下载、安装CentOS7操作步骤

CentOS7.9下载和安装操作步骤

weixin_45608163的博客 1万+

Mooncake架构:基于KVCache解耦的LLM推理优化方案

在大语言模型推理中,KVCache是Transformer解码过程中用于缓存历史Key/Value向量的核心数据结构,它避免了序列重复计算,但会随上下文长度线性增长,成为显存占用的主要部分。其原理是在自回归生成时,将已计算过的注意力键值对存储下来,供后续Token生成时直接使用,从而提升计算效率。这项技术的核心价值在于,通过高效管理KVCache,可以显著降低长序列推理时的显存压力,提升GPU资源利用率。在实际应用场景中,尤其是在处理长上下文对话、高并发请求时,KVCache的管理策略直接决定了服务的吞吐量

weixin_35753431的博客 534

基于Webpack和ES6构建NPM包

用ES6编写代码,使用Webpack打包导出模块,并发布到NPM社区,添加基于Travis-CI和Coveralls的持续集成到Github项目中 特性 基于Webpack 4 使用ES6编写源码 模块支持: 在浏览器环境下使用,通过&lt;script&gt;标签来引入这个类库 通过NPM安装使用 兼容 ES6(ES2015) 的模块系统、CommonJS 和 AMD 模块规范 使用...

weixin_34327223的博客 942

OpenClaw界面操作手册:命令行与交互模式的正确打开方式

"test": {"description": "运行项目的测试套件","prompt": "请执行项目的测试命令,并分析测试结果。如果有失败的测试,请提供修复建议。},"lint": {"description": "运行代码检查","prompt": "请运行代码检查工具,分析所有警告和错误,并提供修复建议。},"doc": {"description": "为当前文件生成文档","prompt": "请为当前打开的文件生成完整的API文档,包括函数说明、参数描述、返回值类型和使用示例。

gaoxiang_120的专栏 3148

webpack打包时通过library和libraryTarget设置资源输出方式

output.library和output.libraryTarget属性可能大家都会比较陌生,因为一般如果只在项目中使用 webpack 不需要关注这两个属性,但是如果是开发类库,那么这两个属性就是必须了解的。 类库的几种方式: script标签 AMD commonjs ES6 module <script src="demo.js"></...

前端361 7194

银河麒麟高级服务器V11操作系统安装部署zabbix监控平台的实操保姆级教程

本文详细介绍了在《银河麒麟高级服务器V11上安部署Zabbix监控系统的全过程》涵盖了zabbix监控系统涉及到的所有软件安装、参数优化、服务启动验证及防火墙配置等一系列实操。其中关于安装过程报错undefined symbol: usmAES256CiscoPrivProtocol;ares_reinit等依赖库问题进行了详细记录与分析解决;还提供了Web前端中文显示修复方案和Admin密码修改方法。实现监控平台的100%部署上线,实现对业务系统的实时监控,保证业务的稳定运行。

提供C#相关开发 、云计算、运维测试、网络安全相关技术分享与服务,有意向可联系。 531

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

使用webpack打包工具实现浏览器支持es6模块

浏览器目前对于es6的支持有限。我们通常会使用babel转码器经es6转为es5实现浏览器的支持。但是babel默认只转换新的JavaScript句法(syntax),而不转换新的API,比如Iterator、Generator、Set、Maps、Proxy、Reflect、Symbol、Promise等全局对象,以及一些定义在全局对象上的方法(比如Object.assign)都不会转码。而且像i...

qq_33745501的博客 2210

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

webpack es6 npm包_【译】发布你自己的npm包

备注:npm模块有个神奇的样板。这篇文章是基于我从设置中学到的东西。如今,NPM已经成为javascript库的事实上的注册表。特别是React,Angular和其他前端库主导的网络和node.js接管的服务器端,NPM软件包比以往任何时候都更受欢迎。通常,我们会在代码中引入实用包,比如typy,sugar,并轻松的使用它们。那么,你有没有想过编写自己的实用程序/库,并将其发布到NPM上面,以便在...

weixin_39744606的博客 412

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

零知识加密分享工具PrivateBin的安全部署与实践

零知识证明(Zero-Knowledge Proof)是一种密码学技术,允许一方在不泄露任何实际信息的情况下向另一方证明自己知道某个秘密。其核心原理通过复杂的数学算法实现,既能验证真实性,又能保护隐私。在数据安全领域,这项技术被广泛应用于加密通信、身份验证等场景。PrivateBin作为典型的零知识加密工具,采用客户端加密(AES-256)与服务端存储分离的架构,确保即使服务器被入侵,攻击者也无法解密数据。通过Sealos云原生平台可快速部署该方案,适用于企业合同传递、研发资料共享等高安全需求场景,同时支持

weixin_34405354的博客 641

为什么自己写的组件库被引用总是报错——详解webpack的library和libraryTarget

如果我们仅仅是实现一个项目,我们大概率不会关注到webpack output中的这两个属性。但是如果我们是实现一个组件库,那么这两个属性就变得至关重要了。本文从自己之前遇到的一个问题说起,继而引申出library和libraryTarget属性。 1. 故事起源 当我自己开始写第一个组件库的时候,很快我就撸好了框架的代码,然后我兴致冲冲的...

weixin_34037515的博客 1257

webpack组织模块的原理 - external模块

这篇文章讨论Webpack打包library时经常需要用到的一个选项external,它用于避免将一些很通用的模块打包进你发布的library里,而是选择把它们声明成external的模块,在你的library被上层使用后,在最后阶段由Webpack统一把这个external的依赖模块打包进来。 external选项一般都是用在打包lib...

weixin_33712881的博客 603
上一篇: How it's made species-in-pieces
下一篇: 再说CSS3渐变——线性渐变
abxn2002
博客等级 码龄20年 13粉丝 34原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值