webpack开发本地library的神坑

最近在给隔壁组做项目拆分,将几个项目的通用部分拆出来成为独立的资源项目

原理是通过npm install 的时候 ,允许设置为本地文件

npm i dep@file:../dep

这样就能在项目中引用一个本地的类库--公司的版本库还是老掉牙的svn

这样就能通过公共的资源项目来管理公共模块,其他业务性的项目就能简单的引用了一下,当公共资源项目修改了之后,业务项目只需要简单的update一下就好了

理想很丰满,现实比较残酷

首先确实以前几乎没怎么用过webpack,都是什么vue-cli之类的直接初始化好,直接用,也没管过这东西具体是怎么配置的

更别提写一个library了

首先我们的项目是被拆成三部分:业务项目,公共代码部分,公共UI组件部分

公共代码起个名字:ts-dep

公共代码部分会同时被UI和业务项目引用

公共代码部分比较简单,一个中规中矩的npm package项目,当然我们的项目用的ts,也让我折腾了一下,这一块就不说了
最后得到这样一个项目结构

image.png

package.json文件内容

{
    "name": "ts-dep",
    "version": "1.0.0",
    "description": "",
    "main": "./lib/index.js",
    "typings": "./lib/index.d.ts",
    "scripts": {
        "build": "tsc"
    },
    "keywords": [],
    "author": "",
    "license": "ISC"
}

UI组件起个名字: v-com-dep

index.js中有如下代码

import tsDep from 'ts-dep';

在UI组件中,首先遇到的问题是:

这个项目ts依赖不能被打包进来

这个查一查,都是说用 externals 配置一下就好了

官网文档也没写清楚,就说配置一下这个

结果我按照官网的实例配好之后,得到一个

module.exports = undefined

运行的时候一直报错

最后发现这东西得跟 output 选项配合好
如下代码:libraryTarget 设置成什么,底下的externals就会取对应的选项来进行require

    output: {
        path: resolve('./dist'),
        filename: 'index.js',
        libraryTarget: 'commonjs2',
        globalObject: 'this',
        // libraryExport: 'default',
        library: 'v-com-dep'
    },
//.....
    externals: {
        'ts-dep': {
            commonjs: 'ts-dep',
            commonjs2: 'ts-dep'
        },
        lodash: {
            commonjs: 'lodash',
            commonjs2: 'lodash'
        }
    },

这样配置之后,就能在编译出来的代码中看到对应的模块由

module.exports = undefined

变成了

/* 6 */
/***/ (function(module, exports) {

module.exports = require("ts-dep");

/***/ }),
//....... 和
/* 8 */
/***/ (function(module, exports) {

module.exports = require("lodash");

/***/ })

第一步搞定了


现在开始搞第二步:在业务项目中调用这两个模块

业务项目也起个名字: deps

那么deps/package.json中就有两个依赖

{
  "dependencies":{
     "ts-dep": "file:../ts-dep",
     "v-com-dep": "file:../v-com-dep",
  }
}

在index.js中有以下代码

import tsDep from 'ts-dep';
import vComDep from 'v-com-dep';

结果这个配置,打包出来之后

ts-dep被引入了两次!!!

查看打包出来的文件

很明确,同一个包引入了两次,分别给的ID是'WQi9'和'/wiT1'(这个反正不固定,是这个意思就行)

我当场就哭了,尼玛折腾了这么久,给我两份算怎么回事?

代码体积都是小事,问题是两边的状态不统一!这个很坑啊

我项目里需要设置状态的,不互通的话我怎么设置?

在通用项目里头有一个上传图片的公共组件,允许设置上传图片是否开启压缩,但是对应的界面组件又在UI组件里头

我现在引用资源项目设置了不允许压缩,结果UI项目读不到,我还要这个有啥用??

恨死了。。。。。

但是自己挖的坑,怎么着也得走出来不是?

继续吧,从网上的一些现有的类库入手,比如element-ui,这里面有个peerDependency:vue

看看这个会不会打包两次。。。当然不会啦

所以看看这个破玩意儿跟我的配置有啥区别?结论是没有。。。

我再哭会去。。。

再去研究一下webpack官方提供的library demo,是不是我漏掉了什么东西?

研究了几个小时,结论是没有,我直接把官网的例子clone下来到本地,一样会在最终打包文件中出现两个lodash

难不成天要亡我???

朕的天下保不住了?

仔细看看这两份打包出来的内容吧,貌似是一毛一样的。。。

稍等,这个是lodash的源码,前面的说明里头有一行(我把压缩关了,可以直接看打包出来的源码,webpack@4配置mode:'none',webpack@3将uglifyplugin那一段关掉就好了)

/*
 * Lodash 
 */

但是两份差一个字母,另外一份长这个样子

/*
 * lodash 
 */

一个是大写的L,一个是小写的l

如果是同一份代码出来的,怎么会差一个字母呢??

所以只能说明这里是两份代码!!

为什么会有两份代码呢?

看看代码好了,结果,我发现:在deps的node_modules下有一个lodash,在node_modules/v-com-dep/node_modules下还有一个lodash,且两个lodash刚好就是差一个字母!

deps
  node_modules
    lodash    * Lodash 
    v-com-dep
      node_modules
        lodash  * lodash    

至此,此案告破,就是因为本地安装的时候,yarn直接将整个目录拷进去了(npm 会做一个类似快捷方式的东西放进去,结果是一样的)

v-com-dep/node_modules目录删掉(我这里没有其他依赖,可以删掉)就好了(至于为什么我就不解释了,之前确实没想到会是这里的问题)

看来在开发本地程序的时候,还得像个办法来解决一下这个安装问题。
这个就是小问题了,问题原因找到了~~~~

你可能感兴趣的:(webpack开发本地library的神坑)