Open jiangjiu opened 6 years ago
之前写的san-webpack-loader在近期的几个运营项目的生产环境中进行了实践,很幸运的是并没有什么太大的问题,提高了开发体验和效率。
然而,就在新项目重新开坑的时候,一个让人意想不到的问题出现了:
一个新同学配发了windows本,新的环境竟然跑不起来。。
折磨了半天多的时间,终于把这个bug修了,在此总结一下。
在Mac环境中,路径分隔符是/,san-webpack-loader中,需要将.san文件的style标签抽离,计算成webpack4的内联loader引入。
/
san-webpack-loader
.san
const styleLoader = isProduction ? `!${rootContext}/node_modules/mini-css-extract-plugin/dist/loader.js` : '!style-loader';
涉及到路径计算及拼接时,想当然的就直接用/进行了字符串拼接。
但是!!!,windows环境的路径分隔符是正好相反的\反向斜杠。。。 在windows中编译出来的代码是这样的:
\
// 正反斜杠都存在了 import 'D:\work\aaa\bbb\node_modules/nimi-css-extract-plugin/dist/loader.js'
很明显这是不行的。
之前上线的几个项目中,开发同学清一色的mac💻,完美的避开了windows环境这个差异。
怎么解决呢?
Node.js的path模块了解一下。
path
先来看几个东东。
业务中最常用的两个api了,处理相对路径及绝对路径。
path.join('/foo', 'bar', 'baz/asdf', 'quux', '..'); // Mac中 返回: '/foo/bar/baz/asdf'
Mac中返回的就很正常。
windows中,会返回双反斜杠的结果。
值得注意的是,即使join的参数中带有正斜杠 / ,windows环境下也会处理成反斜杠。
这个字段提供了平台特定的路径片段分隔符:
Windows 上是 \ POSIX 上是 / 例如,在 POSIX 上:
'foo/bar/baz'.split(path.sep); // 返回: ['foo', 'bar', 'baz']
在 Windows 上:
'foo\\bar\\baz'.split(path.sep); // 返回: ['foo', 'bar', 'baz']
注意:在 Windows 上,斜杠字符(/)和反斜杠字符(\)都可作为路径分隔符; 但 path 的方法只添加反斜杠(\)。
有了上述一些Api,很自然的想到可以将路径先分隔开,再通过path.join/path.resolve下的API进行处理,就可以得到统一的路径字符串了(都是正斜杠/都是反斜杠)。
path.join/path.resolve
import 'D:\work\aaa\bbb\node_modules\nimi-css-extract-plugin\dist\loader.js' // windows下的处理结果 o(╥﹏╥)o
解bug,一次过是不存在的,遇到更多的bug,这才是生活。
很显然,我忽略了一个重要的问题:这个路径字符串是要丢给es modules处理的。 人家不认反斜杠。。。
也就是说,我需要把windows/mac下的字符串统一成正斜杠才行。
POSIX,Portable Operating System Interface。 是UNIX系统的一个设计标准,很多类UNIX系统也在支持兼容这个标准,如Linux。 遵循这个标准的好处是软件可以跨平台。 所以windows也支持就很容易理解了,那么多优秀的开源软件,支持了这个这些软件就可能有windows版本,就可以完善丰富windows下的软件。
POSIX,Portable Operating System Interface。
是UNIX系统的一个设计标准,很多类UNIX系统也在支持兼容这个标准,如Linux。
遵循这个标准的好处是软件可以跨平台。 所以windows也支持就很容易理解了,那么多优秀的开源软件,支持了这个这些软件就可能有windows版本,就可以完善丰富windows下的软件。
大名鼎鼎的POSIX标准,在path下也有实现。
举个栗子:
path.posix.join('/foo', 'bar', 'baz/asdf', 'quux', '..'); // windows中 也会返回: '/foo/bar/baz/asdf'
任何环境下,都会返回unix标准的结果,这个API简直是不能再赞了👍
有了上面的API,应该是可以统一成正斜杠了吧?
然后,这就是生活。
另一个问题来了,绝对路径...看下面这个例子:
// 业务中上层传递过来了一个特殊的rootContext变量 // 无法确定是否是绝对路径还是相对路径 path.posix.join(...rootContext.split(path.sep)) // 如果rootContext是一个绝对路径, 就会变成这样 path.posix.join(...'/User/xxx/a/b'.split(path.sep)) // Mac下 'User/xxx/a/b' path.posix.join(...'D:\\xxx\\a\\b'.split(path.sep)) // windows下 'D:/xxx/a/b'
这种情况下,windows是可以了,但是Mac下因为提前分割了路径,join后丢掉了绝对路径的那个行首斜杠。
if (/^win/.test(require('os').platform())) { // windows环境 ...
团队生产力工具大一统🖥,实在是太TM重要了。
之前写的san-webpack-loader在近期的几个运营项目的生产环境中进行了实践,很幸运的是并没有什么太大的问题,提高了开发体验和效率。
然而,就在新项目重新开坑的时候,一个让人意想不到的问题出现了:
一个新同学配发了windows本,新的环境竟然跑不起来。。
折磨了半天多的时间,终于把这个bug修了,在此总结一下。
问题
在Mac环境中,路径分隔符是
/
,san-webpack-loader
中,需要将.san
文件的style标签抽离,计算成webpack4的内联loader引入。涉及到路径计算及拼接时,想当然的就直接用
/
进行了字符串拼接。但是!!!,windows环境的路径分隔符是正好相反的
\
反向斜杠。。。 在windows中编译出来的代码是这样的:很明显这是不行的。
之前上线的几个项目中,开发同学清一色的mac💻,完美的避开了windows环境这个差异。
Node.js的path模块
怎么解决呢?
Node.js的
path
模块了解一下。先来看几个东东。
path.join && path.resolve
业务中最常用的两个api了,处理相对路径及绝对路径。
Mac中返回的就很正常。
windows中,会返回双反斜杠的结果。
值得注意的是,即使join的参数中带有正斜杠 / ,windows环境下也会处理成反斜杠。
path.sep
这个字段提供了平台特定的路径片段分隔符:
Windows 上是
\
POSIX 上是/
例如,在 POSIX 上:在 Windows 上:
注意:在 Windows 上,斜杠字符(/)和反斜杠字符(\)都可作为路径分隔符; 但 path 的方法只添加反斜杠(\)。
问题again
有了上述一些Api,很自然的想到可以将路径先分隔开,再通过
path.join/path.resolve
下的API进行处理,就可以得到统一的路径字符串了(都是正斜杠/都是反斜杠)。解bug,一次过是不存在的,遇到更多的bug,这才是生活。
很显然,我忽略了一个重要的问题:这个路径字符串是要丢给es modules处理的。 人家不认反斜杠。。。
也就是说,我需要把windows/mac下的字符串统一成正斜杠才行。
path.posix
大名鼎鼎的POSIX标准,在path下也有实现。
举个栗子:
任何环境下,都会返回unix标准的结果,这个API简直是不能再赞了👍
问题again😤
有了上面的API,应该是可以统一成正斜杠了吧?
然后,这就是生活。
另一个问题来了,绝对路径...看下面这个例子:
这种情况下,windows是可以了,但是Mac下因为提前分割了路径,join后丢掉了绝对路径的那个行首斜杠。
解决
总结
团队生产力工具大一统🖥,实在是太TM重要了。
参考