前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片NEW
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 业务场景题真实业务问题与追问
  • 查漏补缺常见问题解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
    • AI 定制路线NEW按你的简历现排
    • AI 知识地图NEW串起全站知识点
  • 动态
    • AI 热点NEWAI 每日动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
AI 助手NEW
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片NEW
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 业务场景题真实业务问题与追问
  • 查漏补缺常见问题解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
    • AI 定制路线NEW按你的简历现排
    • AI 知识地图NEW串起全站知识点
  • 动态
    • AI 热点NEWAI 每日动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
AI 助手NEW
旧版
  • JavaScript Part 1

    • Ajax总结篇
    • Canvas 绘制八大行星
    • DOM编程之API学习总结篇
    • JavaScript事件机制
    • JavaScript代码片段100个
    • JavaScript作用域分析总结
    • JavaScript原型链回顾
    • JavaScript及jQuery中的各种宽高属性图解
    • JavaScript工程项目的一系列最佳实践
    • JavaScript常用API合集
    • JavaScript数组、字符串、对象常用方法
    • JavaScript数组方法总结篇
    • JavaScript深浅拷贝
    • JavaScript运动框架之速度时间版本
    • JavaScript运行机制Event Loop
    • JavaScript防抖节流原理
    • Javascript中的复制粘贴功能
    • Javascript数组详解
    • OOP之原型与原型链
    • Object.defineProperty详解
    • V8源码浅析JS数组常见方法
    • await 在 forEach 中不生效解决方案
    • iframe+表单跨域提交POST请求
    • javascript笔记总结篇
    • 业务中处理数据结构常用的JS方法
    • 作用域
    • 你真的掌握变量和类型了吗
    • 前后端分离之数据Mock
    • 原型与原型链
    • 原生JS补给(上)
    • 如何写出一个惊艳面试官的深拷贝
    • 带你填一些JS容易出错的坑
    • 彻底弄懂 JavaScript 执行机制
    • 执行上下文 执行栈
    • 正则回顾总结
    • 正则基础知识
    • 正则完整篇
    • 正则表达式
    • 浅析Promise原理
    • 浅谈JavaScript中的异步处理
    • 深拷贝 vs 浅拷贝
    • 聊一聊typeof instanceof 实现原理.
    • 聊一聊闭包
    • 高阶函数map reduce filter
  • JavaScript Part 2

  • CSS

  • HTML

  • Jquery

  • ES6

  • 小程序

  • Vue

  • React

  • 深入React

  • React Native

  • NodeJS

  • Angular

  • TypeScript

  • Webpack

  • 浏览器

  • 移动端

  • 前端工程化

  • Electron

  • HTTP

  • Nginx

  • Linux

  • 数据结构与算法

  • LeetCode算法题

  • 综合

完整面试题地址:
作者:程序员poetry
扫码关注作者公众号:「前端进阶之旅」 每天分享技术干货
前端进阶之旅公众号二维码

webpack library篇|博客系列

# 一、webpack-numbers案例

这里我也不折腾了, 就以官网提供的案例进行讲解吧.

首先让我们明确要做什么事情.

  1. 本地编写创建一个名为lindaidai-webpack-numbers的项目(也就是library)
  2. 这个library的功能是导出两个方法, 能实现数字与字符串的互相转换
  3. library中用到了lodash这个工具库
  4. 将library打包发布到NPM上, 其它用户能够通过npm install的方式下载使用
  5. 外部化lodash, 也就是我们library虽然使用了lodash, 但是并不要将它打包到我们的bundle中
  6. 用户能通过ES2015模块, CommonJS模块, script脚本引入我们的library并使用它

该 library 的使用方式如下:

// ES2015模块引入
import * as webpackNumbers from 'lindaidai-webpack-numbers'
// CommonJS模块引入
var webpackNumbers = require('lindaidai-webpack-numbers')

// ES2015模块和CommonJS模块都是这样调用的:
webpackNumbers.numToWord(2)

// AMD模块引入
require(['lindaidai-webpack-numbers'], function (webpackNumbers) {
  // AMD 模块调用
  webpackNumbers.wordToNum('Two');
})
@前端进阶之旅: 代码已经复制到剪贴板

用户还可以通过 script 标签来加载和使用此 library:

<!doctype html>
<html>
  ...
  <script src="https://unpkg.com/lindaidai-webpack-numbers"></script>
  <script>
    // ...
    // 全局变量
    webpackNumbers.wordToNum('Five')
    // window 对象中的属性
    window.webpackNumbers.wordToNum('Five')
    // ...
  </script>
</html>
@前端进阶之旅: 代码已经复制到剪贴板

# 创建library的项目结构

让我们使用webpack快速的构建一个本地的library.

由于有了之前webpack的基础, 我相信你构建起来应该也会很快.

mkdir lindaidai-webpack-numbers && cd lindaidai-webpack-numbers
npm init -y
cnpm i --save-dev webpack webpack-cli lodash
touch webpack.config.js
mkdir src && cd src
touch index.js
touch ref.json
@前端进阶之旅: 代码已经复制到剪贴板

一顿操作之后, 项目结构变成了这样:

lindaidai-webpack-numbers
	|- /node_modules
	|- /src
		|- index.js
		|- ref.json
	|- package.json
	|- webpack.config.js
@前端进阶之旅: 代码已经复制到剪贴板

之后来简单的编写一下文件中的代码:

src/ref.json:

[{
        "num": 1,
        "word": "One"
    },
    {
        "num": 2,
        "word": "Two"
    },
    {
        "num": 3,
        "word": "Three"
    },
    {
        "num": 4,
        "word": "Four"
    },
    {
        "num": 5,
        "word": "Five"
    },
    {
        "num": 0,
        "word": "Zero"
    }
]
@前端进阶之旅: 代码已经复制到剪贴板

src/index.js:

import _ from 'lodash';
import numRef from './ref.json';

export function numToWord(num) {
    return _.reduce(numRef, (accum, ref) => {
        return num === ref.num ? ref.word : accum
    })
}

export function wordToNum(word) {
    return _.reduce(numRef, (accum, ref) => {
        return ref.word === word && word.toLowerCase() ? ref.num : accum;
    }, -1);
};
@前端进阶之旅: 代码已经复制到剪贴板

webpack.config.js:

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'webpack-numbers.js'
  }
};
@前端进阶之旅: 代码已经复制到剪贴板

# 配置webpack.config.js

编写完成上面👆几个文件之后, 打包之后生成的dist目录就只有一个webpack-numbers.js文件:

/dist
	|- webpack.numbers.js
@前端进阶之旅: 代码已经复制到剪贴板

但是我们注意到生成的js中包含了lodash:

lindaidai@LinDaiDaideMacBook-Pro lindaidai-webpack-numbers % npm run build

> lindaidai-webpack-numbers@1.0.0 build /Users/lindaidai/codes/webpack/lindaidai-webpack-numbers
> webpack

Hash: e49f78747376a068a282
Version: webpack 4.41.5
Time: 1544ms
Built at: 2020-02-10 6:57:59 PM
             Asset      Size  Chunks             Chunk Names
+ webpack-numbers.js  72.4 KiB       0  [emitted]  main
@前端进阶之旅: 代码已经复制到剪贴板

所以导致webpack-number.js非常大.

# 外部化lodash(配置externals)

因此对于这种我们额外引入的module, 我们更倾向于把 lodash 当作 peerDependency。也就是说,用户应该已经将 lodash 安装好.

所以,你可以放弃对外部 library 的控制,而是将控制权让给使用 library 的用户。

这个功能需要靠externals配置:

webpack.config.js:

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'webpack-numbers.js'
-  }
+  },
+  externals: {
+  	lodash: {
+  		commonjs: 'lodash',
+  		commonjs2: 'lodash',
+  		amd: 'lodash',
+  		root: '_'
+  	}
  }
};
@前端进阶之旅: 代码已经复制到剪贴板

这意味着你的 library 需要一个名为 lodash 的依赖,这个依赖在用户的环境中必须存在且可用。

# 暴露library

因为我们编写的library可能会在不同的执行环境中用到,例如 CommonJS,AMD,Node.js 或者作为一个全局变量.

所以为了实现这个功能, 我们首先需要在oupout中添加library属性:

webpack.config.js:

  var path = require('path');

  module.exports = {
    entry: './src/index.js',
    output: {
      path: path.resolve(__dirname, 'dist'),
      filename: 'webpack-numbers.js',
+     library: 'webpackNumbers'
    },
    externals: {
      lodash: {
        commonjs: 'lodash',
        commonjs2: 'lodash',
        amd: 'lodash',
        root: '_'
      }
    }
  };
@前端进阶之旅: 代码已经复制到剪贴板

添加了library属性是为了将library在打包之后的bundle文件中暴露一个名为webpackNumbers的全局变量.

但是还需要指定我们的library在怎样的环境中使用.

这依靠于libraryTarget属性, 它可以控制library如何以不同方式暴露的选项.

主要有以下几个值:

  • 变量:作为一个全局变量,通过 script 标签来访问(libraryTarget:'var')。
  • this:通过 this 对象访问(libraryTarget:'this')。
  • window:通过 window 对象访问,在浏览器中(libraryTarget:'window')。
  • UMD:在 AMD 或 CommonJS 的 require 之后可访问, 也就是以上几种环境都可以访问(libraryTarget:'umd')

如果设置了 library 但没设置 libraryTarget,则 libraryTarget 默认为 var

所以在此处我希望在所有的环境中都能使用, 则只要设置libraryTarget: 'umd':

  var path = require('path');

  module.exports = {
    entry: './src/index.js',
    output: {
      path: path.resolve(__dirname, 'dist'),
      filename: 'webpack-numbers.js',
      library: 'webpackNumbers',
+     libraryTarget: 'umd'
    },
    externals: {
      lodash: {
        commonjs: 'lodash',
        commonjs2: 'lodash',
        amd: 'lodash',
        root: '_'
      }
    }
  };
@前端进阶之旅: 代码已经复制到剪贴板

# 发布至NPM

现在我们希望的是将打包之后的dist文件与这整个项目一起发布到NPM上.

所以我们需要执行打包命令让library项目目录结构变为:

lindaidai-webpack-numbers
	|- /dist
		|- webpack.numbers.js
	|- /src
		|- index.js
		|- ref.json
	|- package.json
	|- webpack.config.js
@前端进阶之旅: 代码已经复制到剪贴板

(如果你的项目没有配置打包命令的话需要在package.json中配置一个脚本命令"build": “webpack”, 这样你就可以执行npm run build指令进行打包了)

# 登录npm

npm adduser //创建用户(如果你没有npm账号的话)
or
npm login //登录用户
@前端进阶之旅: 代码已经复制到剪贴板

可以使用:

npm whoami
@前端进阶之旅: 代码已经复制到剪贴板

检测用户是否登录上了npm

# 安装publish

首先需要安装publish

npm i -g publish
@前端进阶之旅: 代码已经复制到剪贴板

# 发布library

← gulp学习总结篇loader篇 →

fe
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片NEW
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 业务场景题真实业务问题与追问
  • 查漏补缺常见问题解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
    • AI 定制路线NEW按你的简历现排
    • AI 知识地图NEW串起全站知识点
  • 动态
    • AI 热点NEWAI 每日动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
AI 助手NEW
旧版
  • JavaScript Part 1

    • Ajax总结篇
    • Canvas 绘制八大行星
    • DOM编程之API学习总结篇
    • JavaScript事件机制
    • JavaScript代码片段100个
    • JavaScript作用域分析总结
    • JavaScript原型链回顾
    • JavaScript及jQuery中的各种宽高属性图解
    • JavaScript工程项目的一系列最佳实践
    • JavaScript常用API合集
    • JavaScript数组、字符串、对象常用方法
    • JavaScript数组方法总结篇
    • JavaScript深浅拷贝
    • JavaScript运动框架之速度时间版本
    • JavaScript运行机制Event Loop
    • JavaScript防抖节流原理
    • Javascript中的复制粘贴功能
    • Javascript数组详解
    • OOP之原型与原型链
    • Object.defineProperty详解
    • V8源码浅析JS数组常见方法
    • await 在 forEach 中不生效解决方案
    • iframe+表单跨域提交POST请求
    • javascript笔记总结篇
    • 业务中处理数据结构常用的JS方法
    • 作用域
    • 你真的掌握变量和类型了吗
    • 前后端分离之数据Mock
    • 原型与原型链
    • 原生JS补给(上)
    • 如何写出一个惊艳面试官的深拷贝
    • 带你填一些JS容易出错的坑
    • 彻底弄懂 JavaScript 执行机制
    • 执行上下文 执行栈
    • 正则回顾总结
    • 正则基础知识
    • 正则完整篇
    • 正则表达式
    • 浅析Promise原理
    • 浅谈JavaScript中的异步处理
    • 深拷贝 vs 浅拷贝
    • 聊一聊typeof instanceof 实现原理.
    • 聊一聊闭包
    • 高阶函数map reduce filter
  • JavaScript Part 2

  • CSS

  • HTML

  • Jquery

  • ES6

  • 小程序

  • Vue

  • React

  • 深入React

  • React Native

  • NodeJS

  • Angular

  • TypeScript

  • Webpack

  • 浏览器

  • 移动端

  • 前端工程化

  • Electron

  • HTTP

  • Nginx

  • Linux

  • 数据结构与算法

  • LeetCode算法题

  • 综合