记一次错:Vue 构建项目后使用 npm link 失败

不想看过程可以直接看最后的总结 :)

起因

前天的时候就遇到了一个非常棘手的问题,在高高兴兴写完 Vue 项目后,使用 npm link 在别的项目里导入自己的包报错(这里的变量都用 xxxx 或者 yyyy 来表示啦):

"export 'default' (imported as 'xxx') was not found in 'xxxx

但是如果我从 npm 上下载自己的包是不报错的,而使用 npm link 本地调试的时候就报上面的错。而且我还自己点进原文件看了下,npm 下载的和本地 npm linkxxx.umd.js 根本就是一毛一样啊,为什么两边的结果不一样呢?

谷歌了一波后发现别人也有有同样的问题

下面他就说了两边出现不同结果的问题:

尤大也回复了,但是他说这不是 vue-cli 的问题,是 webpack 自己没有将文件转成 ES6 module 的形式。真的是看的我一脸问号。

为什么报错

没办法,他不说解决方法,我自己总得解决吧。首先将谷歌一下报错信息,得到的解答是: 同时使用了 importmodule.exports 语法,所以才报错。什么?这怎么可能,两边的项目肯定都没这样用过。除非是。。。。。我引入的那个打包后的文件 xxx.umd.js 是有 module.exports 语句的。

难道真的是 Webpack 没有转成 ES6 的问题?

坑:官方文档

第一反应是官方文档应该有教怎么打包项目的,里面说不定有答案,所以回去认真读了下文档,可是:

woc,Webpack 真的不能转成 ES6 Module 的啊。所以现在问题变成了:Webpack 将原来的项目打包成 ES5 的版本,然后在新项目里用 import 里引入了带有 module.exports 语句的文件,从而导致上面的报错。

坑:Vue CookBook

这时我注意到上面出现同样问题的大哥说到可以用 Rollup.js 来打包,这就可以打包出 ES6 语法的 JS了。马上开搞,然后查到了 Vue CookBook:

果然可以打包成 xxxx.esm.js 的方法,但是原来的项目是用 Webpack + Vue 来构建的,使用两套打包工具真的好吗?虽然不太好,我试了下,奈何在全局引入 .scss 文件的地方试了一万个方法都不行,只能放弃这个方法。从头开始分析。

Webpack 是真的坑

说实话那天我就放弃了,本地调试不行就算了吧,不就搞很多个 npm 版本么。后面还是 Jetbrains 给了我灵感。

今天我想删除某个文件的时候发现了这个选项:

Exclude?嗯。。。曾经的我就在 webpack.config.js 里看到过这个选项,好像说是可以不对某些文件进行编译,这样就能在 yarn run build 的时候提高性能。再结合一下前面分析的“没有转成 ES6 语法”的报错,好像有点说通了。非常有可能 Webpack 对从 npm 下载下来的文件进行预先编译,将其转成 ES6,而本地引入的话没有预先编译

后面我做了如下测试:

  1. 将 /dist 下所有文件拷到新项目的 /src 里,直接本地引入,同样报错。
  2. 将 /dist 下所有文件拷贝到新项目的 /node_modules 里,直接本地使用 import '/node_modules/xxx/xxx.umd.js' 引入,成功!
  3. 在新项目使用 npm link xxx 后,在 /node_modules 里用上面的 import '/node_modules/xxx/xxx.umd.js' 引入,失败。

再次分析

上面 1 和 2 的测试足以说明我的猜想是对的,Webpack 会对 /node_modules 下的文件进行预先编译,再引入到真实项目中,这样就没有 module.exports 的语句了,所以也就不会报错了。

但是为什么 3 也失败呢?我在命令行里输入 ls -a 也发现自己的 xxx 包呀,说明我的原来的项目包也在 /node_modules 下呀。后面想到 Mac 的 link 命令,npm link 说不定是创建软链接而已,所以用 Finder 打开新项目的 /node_modules ,果然这是个软链接:

而这个软链接指向的真实地址是本机的别的地址,也就是说这个包不在项目的 /node_modules 文件夹下。所以不会预先被编译,再次印证上面的猜想。

现在终于真相大白了。

总结

为什么报错

如果使用下载的 npm package,那么 Webpack 在项目引入前将代码编译成 ES6 模块语法,所以这时候不会报错。

如果使用 npm link 会将 npm 包放在本机的全局 /node_modules 下,新项目的 /node_modules 下只是一个软链接(快捷方式)。而不在新项目 /node_modules 下的文件都不会预先编译成 ES6 模块方法。在项目里引入也就等同于下面代码:

// B.js
module.exports = {
}

// A.js
import "B.js"

而这两种语法混合使用就会报错:

"export 'default' (imported as 'xxx') was not found in 'xxxx

解决方法

我简单搜索了一下没找到什么解决方法(真的不知道要怎么搜这种问题了)。所以现在最笨的方法就是每次 yarn run build 后将 /dist 目录拷到别的项目的 /node_modules 下,然后在那个项目引入就可以了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,841评论 5 472
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,415评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,904评论 0 333
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,051评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,055评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,255评论 1 278
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,729评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,377评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,517评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,420评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,467评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,144评论 3 317
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,735评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,812评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,029评论 1 256
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,528评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,126评论 2 341