美文网首页程序员饥人谷技术博客JavaScript 进阶营
记一次错:Vue 构建项目后使用 npm link 失败

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

作者: 写代码的海怪 | 来源:发表于2019-01-20 09:11 被阅读1次

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

    起因

    前天的时候就遇到了一个非常棘手的问题,在高高兴兴写完 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 下,然后在那个项目引入就可以了。

    相关文章

      网友评论

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

        本文链接:https://www.haomeiwen.com/subject/bgotjqtx.html