天天看點

from scapy.all import * 調試失敗_記一次錯:Vue-建構項目後使用 npm link 失敗

不想看過程可以直接看最後的總結 :)

起因

前天的時候就遇到了一個非常棘手的問題,在高高興興寫完 Vue 項目後,使用

npm link

在别的項目裡導入自己的包報錯(這裡的變量都用 xxxx 或者 yyyy 來表示啦):

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

但是如果我從 npm 上下載下傳自己的包是不報錯的,而使用

npm link

本地調試的時候就報上面的錯。而且我還自己點進原檔案看了下,npm 下載下傳的和本地

npm link

xxx.umd.js

根本就是一毛一樣啊,為什麼兩邊的結果不一樣呢?

谷歌了一波後發現别人也有有同樣的問題:

from scapy.all import * 調試失敗_記一次錯:Vue-建構項目後使用 npm link 失敗

下面他就說了兩邊出現不同結果的問題:

from scapy.all import * 調試失敗_記一次錯:Vue-建構項目後使用 npm link 失敗

尤大也回複了,但是他說這不是 vue-cli 的問題,是 webpack 自己沒有将檔案轉成 ES6 module 的形式。真的是看的我一臉問号。

為什麼報錯

沒辦法,他不說解決方法,我自己總得解決吧。首先将谷歌一下報錯資訊,得到的解答是:

同時使用了

import

module.exports

文法,是以才報錯

。什麼?這怎麼可能,兩邊的項目肯定都沒這樣用過。除非是。。。。。我引入的那個打包後的檔案

xxx.umd.js

是有

module.exports

語句的。

from scapy.all import * 調試失敗_記一次錯:Vue-建構項目後使用 npm link 失敗

難道真的是 Webpack 沒有轉成 ES6 的問題?

坑:官方文檔

第一反應是官方文檔應該有教怎麼打包項目的,裡面說不定有答案,是以回去認真讀了下文檔,可是:

from scapy.all import * 調試失敗_記一次錯:Vue-建構項目後使用 npm link 失敗

woc,Webpack 真的不能轉成 ES6 Module 的啊。是以現在問題變成了:Webpack 将原來的項目打包成 ES5 的版本,然後在新項目裡用

import

裡引入了帶有

module.exports

語句的檔案,進而導緻上面的報錯。

坑:Vue CookBook

這時我注意到上面出現同樣問題的大哥說到可以用 Rollup.js 來打包,這就可以打包出 ES6 文法的 JS了。馬上開搞,然後查到了 Vue CookBook:

from scapy.all import * 調試失敗_記一次錯:Vue-建構項目後使用 npm link 失敗

果然可以打包成

xxxx.esm.js

的方法,但是原來的項目是用 Webpack + Vue 來建構的,使用兩套打包工具真的好嗎?雖然不太好,我試了下,奈何在全局引入

.scss

檔案的地方試了一萬個方法都不行,隻能放棄這個方法。從頭開始分析。

Webpack 是真的坑

說實話那天我就放棄了,本地調試不行就算了吧,不就搞很多個 npm 版本麼。後面還是 Jetbrains 給了我靈感。

from scapy.all import * 調試失敗_記一次錯:Vue-建構項目後使用 npm link 失敗

今天我想删除某個檔案的時候發現了這個選項:

from scapy.all import * 調試失敗_記一次錯:Vue-建構項目後使用 npm link 失敗

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 ,果然這是個軟連結:

from scapy.all import * 調試失敗_記一次錯:Vue-建構項目後使用 npm link 失敗

而這個軟連結指向的真實位址是本機的别的位址,也就是說這個包不在項目的 /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 下,然後在那個項目引入就可以了。

繼續閱讀