-
Notifications
You must be signed in to change notification settings - Fork 0
Description
背景
因为公司提供的办公电脑是Windows系统,本人之前一直使用的Ubuntu系统开发的,所以就比较难受了。于是我有了用VMware虚拟机安装一个Ubuntu桌面版的想法,经过一番折腾以后,就可以愉快的写代码了~~~
发现问题
在我使用yarn安装项目依赖的时候,总是会出现如下的错误,真是让人苦恼。不如换成npm install 试试,结果如出一辙,报错信息如下所示:
guili@guili-virtual-machine:/mnt/hgfs/UbuntuShare/workspace/my-app$ yarn
yarn install v1.22.10
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
error An unexpected error occurred: "ENOTSUP: operation not supported on socket, symlink '../../../../@babel/parser/bin/babel-parser.js' -> '/mnt/hgfs/UbuntuShare/workspace/my-app/node_modules/@vue/compiler-core/node_modules/.bin/parser'".
info If you think this is a bug, please open a bug report with the information provided in "/mnt/hgfs/UbuntuShare/workspace/my-app/yarn-error.log".
info Visit https://yarnpkg.com/en/docs/cli/install for documentation about this command.于是,我拍案而起,这也太坑了吧。
分析问题
查阅了资料,了解到vmhgfs(应用于VMware共享文件夹的Linux端vfs)不支持symlink(或者可能是不支持Linux和Windows下的符号链接格式互相转换)。原理是安装基于nodejs的项目时,如果安装的模块的package.json 中定义了bin 字段,那么yarn或者npm就会自动创建一个符号链接到node_modules/.bin文件夹下。
因为VMware的“共享文件夹”是不支持自动符号链接转换的,所以这个功能在VMware的“共享文件夹”下是没法正常工作的,就会导致上述的报错信息的出现。
解决方案
一、bin-links
npm提供了bin-links配置项,可以告诉 npm 为包可执行文件创建符号链接(或 Windows 上的 .cmd 垫片)。 设置为 false 使其不这样做。这可以用来解决一些文件系统不支持符号链接的事实,即使在表面上是 Unix 系统上。
npm
你可以直接在~/.npmrc写入,
bin-links=false或者直接命令设置全局的配置如下:
npm config set bin-links=false另外,还可以直接使用
npm install --no-bin-linksyarn
你可以直接在~/.yarnrc写入,
"--*.no-bin-links" true
or
bin-links false或者直接命令设置全局的配置如下:
yarn config set bin-links false另外,还可以直接使用
yarn --no-bin-links二、nodejs脚本
使用上述的方法,只是安装模块的时候不再报错,但是当执行scripts字段下的run命令时,还是会有报错,说找不到某某模块。比如有一个webpack打包的项目,然后已经使用--no-bin-links安装好所以依赖。对于webpack,找到其package.json,发现配置有bin字段:
"bin": {
"webpack": "./bin/webpack.js"
}可知此模块有一个cli入口,入口名和包一致,为webpack,对应执行模块目录内的./bin/webpack.js。
既然无法用符号链接来指向这个文件,我们可以曲线救国,使用脚本完成这个事。首先需要在node_modules目录下创建.bin文件夹,然后创建文件webpack.js,写入内容如下:
#! /bin/bash
node './node_modules/webpack/bin/webpack.js' $*最后的$*是为了将所有命令行参数完整的传给对应脚本。
然后就需要使用chmod命令给已经写好的脚本执行权限。
chmod +x ./node_modules/.bin/webpack然后运行项目就可以正常使用webpack命令了。
完整的代码如下:
const fs = require('fs')
const path = require('path')
// get package list from package.json
const packageList = require('./package.json').devDependencies
// get all package name from packageList
const packageNameList = Object.keys(packageList)
const CLIList = []
const convertPath = (packageName, binaryPath) => path.resolve(`./node_modules/${packageName}/`, binaryPath)
for (let packageName of packageNameList) {
// load package config
const packageConf = require(`./node_modules/${packageName}/package.json`)
if ('bin' in packageConf) {
if (typeof packageConf.bin !== 'string') {
for (let cmd of Object.keys(packageConf.bin)) {
CLIList.push([cmd, convertPath(packageName, packageConf.bin[cmd])])
}
} else {
CLIList.push([packageName, convertPath(packageName, packageConf.bin), true])
}
}
}
if (!fs.existsSync('./node_modules/.bin')) {
fs.mkdir('./node_modules/.bin',()=>{})
} else {
throw new Error('directory .bin exists already')
}
// make script
for (const item of CLIList) {
const [filename, binPath, _] = item
const script = `
#!/bin/bash
node "${binPath}" $*
`
fs.writeFileSync(`./node_modules/.bin/${filename}`, script)
fs.chmodSync(`./node_modules/.bin/${filename}`, 777)
}
console.log(CLIList);终于圆满解决
然后将脚本放到项目的根目录,在安装完node_modules后,运行之前,执行下这个脚本:node ./command_patch.js。
于是乎,困扰了我半天,让我加班的问题终于被我找到原因和圆满解决了~~
当然最直截了当的方法就是不用虚拟机的共享文件夹,直接在虚拟机的其它文件夹下工作。当然也就不会遇到这个问题,也不会折腾这么久了。