最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

【已解决】ReactJS中的@import路径中~波浪线的含义和通过resolve的alias简化导入路径

ReactJS crifan 8276浏览 0评论

之前在折腾Preact项目期间,就看到别人准备好的模板中,对于导入less文件,有这样的写法:

@import ‘~style/helpers’;

就可以导入此处的:

根目录下的src中的helpers.less

其中可以省略less的后缀是之前的

webpack.config.babel.js中的resolve的extensions的效果。

就不多解释了。

要说的是:

为何此处@import导入的路径中的前缀加上一个波浪线~ tilde,是什么作用?

1.因为之前折腾过:

以为此处的波浪线就是:

类似于~表示用户的根目录

-》此处表示当前项目的根目录(webpack.config.js所在目录)

-》且自动识别根目录下的src文件夹呢

-》即:~ = 项目根目录/src 

在别处,也去尝试把:

import SwitchCowfarm from ‘../../components/switch-cowfarm’;

改为:

import SwitchCowfarm from ‘~components/switch-cowfarm’;

或:

import SwitchCowfarm from ‘~/src/components/switch-cowfarm’;

之类的,结果都失败了。

2.在折腾:

【整理】webpack中output的path和publicPath和webpack-dev-server的devServer的contentBase和publicPath的区别和作用

等内容期间知道了可以通过:

module.exports = {
  resolve: {
    alias: {
      //components: path.resolve(__dirname, “src/components”),
      ComponentsDir: path.resolve(__dirname, “src/components”),
      LibDir: path.resolve(__dirname, “src/lib”),
      CommonDir: path.resolve(__dirname, “src/common”),

实现文件夹的别名,从而之前的引用路径可以简化为:

// import {extractSingleStr} from “../../lib/string”;
import {extractSingleStr} from “LibDir/string”;
// import SwitchCowfarm from ‘../../components/switch-cowfarm’;
import SwitchCowfarm from ‘ComponentsDir/switch-cowfarm’;
// import { ROUTE_PREFIX, LOGIN_USER_TYPE } from “../../common/define”;

然后接着去把之前的style也改了:

      // style: path.resolve(__dirname, “src/style”),
      StyleDir: path.resolve(__dirname, “src/style”),

结果就导致出错了:

ERROR in ./~/css-loader?{“modules”:true,”sourceMap”:true,”importLoaders”:1}!./~/postcss-loader/lib?{“sourceMap”:true}!./~/less-loader/dist/cjs.js?{“sourceMap”:true}!./src/container/functions/style.less
Module build failed:
@import ‘~style/helpers’;
^
Can’t resolve ‘style/helpers.less’ in ‘/Users/crifan/dev/dev_root/daryun/Projects/xxx/sourcecode/ucowsapp/ucowsapp/src/container/functions’
      in /Users/crifan/dev/dev_root/daryun/Projects/xxx/sourcecode/ucowsapp/ucowsapp/src/container/functions/style.less (line 1, column 0)
@ ./src/container/functions/style.less 4:14-207 18:2-22:4 19:20-213
@ ./src/container/functions/index.js
@ ./src/container/app.js
@ ./src/index.js
@ multi (webpack)-dev-server/client?http://localhost:8080 webpack/hot/dev-server babel-polyfill ./index.js

很明显,说明此处的:

style: path.resolve(__dirname, “src/style”),

不能随便被改掉,否则之前的:

@import ‘~style/helpers’;

就不工作了。

所以需要去搞清楚,这个波浪号 波浪线~到底是什么意思。

css import 路径中带 波浪线

javascript – less @import 路径问题 – SegmentFault

@import – CSS | MDN

url
是一个表示要引入资源位置的 <string> 或者 <uri> 。 这个 URL 可以是绝对路径或者相对路径。 要注意的是这个 URL 不需要指明一个文件; 可以只指明包名,然后合适的文件会被自动选择 (e.g. chrome://communicator/skin/). See here 了解更多。
list-of-media-queries

css import tilde ~

css3 – What does a `~` tilde in a CSS `url()` do? – Stack Overflow

“So using the prefix ~ at the start of the path tells the Webpack loader to resolve the import “like a module”.”

@import rules in css doesn’t look in node_modules folder · Issue #12 · webpack-contrib/css-loader

“css @import is relative to the current directory. For resolving “like a module” you can prefix ~.”

感觉解释的也不对,~不是代表当前路径的。

“Ah is that documented anywhere?

If I have resolve.alias for my modules will this require a tilde too?

Ah figured it out to get working in resolve.alias. Closing thanks.”

感觉说的是对的:

如果对于之前用resolve.alias定义的路径xxx,此处导入css时用:

@import “~xxx/a/b/c”

估计是这个意思和用法。

How do I include node_modules css files? · Issue #1789 · webpack/webpack

里面的示例,基本上验证了我的猜测。

webpack-contrib/css-loader: css loader module for webpack

css-loader中对于url()中的~ ? 没看懂。

不过:css-loader’s alias 语法上和Webpack的alias一致:

Resolve

sass-true Documentation

提到了说是:

Webpack’s tilde notation

Webpack  tilde notation

Webpack  tilde notation @import

Using url(path) with resolve.alias · Issue #49 · webpack-contrib/css-loader

url(“~common-assets/images/image.png”)

中的~,表示的是这个是个模块module(而不是一个相对路径)

ES6 Import Statement Without Relative Paths Using Webpack – Modus Create

说的是另外的类似的事情:

如何简化导入路径为:

从app的根目录(app root)去导入

webpack 2的配置是:

resolve: {
  modules: [
    path.resolve(‘./src’),
    path.resolve(‘./node_modules’)
  ]
},

-》感觉这个就像后记中提到的:NODE_PATH

Setup New Vue Webpack Project With Bulma | Web Development Notes

“// src/assets/sass/main.scss

@import ‘~bulma/bulma’

Note that the tilde symbol refers Webpack/sass-loader to the node_modules directory.”

import – JavaScript | MDN

Discussion on Rubix – ReactJS Powered Admin Template | Page 16 | WrapBootstrap

“You must prepend a tilde “~” before @import string for importing from node_modules.”

然后继续去调试,去研究:

node_modules tidle ~

Add ~ (tilde) as shortcut for `{}/node_modules`? · Issue #246 · fourseven/meteor-scss

提到了,现在很多的loader都已支持tidle:

webpack-contrib/css-loader: css loader module for webpack

“~module/file.png => module/file.png”

webpack-contrib/less-loader: Less loader for webpack. Compiles Less to CSS.

“webpack resolver

webpack provides an advanced mechanism to resolve files. The less-loader applies a Less plugin that passes all queries to the webpack resolver. Thus you can import your Less modules from node_modules. Just prepend them with a ~ which tells webpack to look up the modules.

@import “~bootstrap/less/bootstrap”;

It’s important to only prepend it with ~, because ~/ resolves to the home-directory. webpack needs to distinguish between bootstrap and ~bootstrap, because CSS and Less files have no special syntax for importing relative files. Writing @import “file” is the same as @import “./file”;”

shama/stylus-loader: A stylus loader for webpack.

“stylus-loader can also take advantage of webpack’s resolve options. With the default options it’ll find files in web_modules as well as node_modules, make sure to prefix any lookup in node_modules with ~. For example if you have a styles package lookup files in it like @import ‘~styles/my-styles. It can also find stylus files without having the extension specified in the @import and index files in folders if webpack is configured for stylus’s file extension.”

【总结】

目前基本上搞清楚了:

目前对于Webpack的好几个加载器:

css-loader

less-loader

sass-loader

stylus-loader

等等,都支持,在@import导入css文件时,路径前加上:

~==波浪号==波浪线==tilde

比如:

import “~bootstrap/less/bootstrap”;

就是告诉Webpack:

以模块的方式去加载(这个css文件)

-》去对应的resolve.modules定义的文件夹中去寻找对应的css文件

-》而resolve.modules往往都定义了node_modules这个文件夹

-》所以就可以去node_modules找对应的css文件了。

对于具体的案例和效果,详见如下解释:

对于目录结构:

src/
    assets/
    components/
        header/
            index.js
        switch-cowfarm/
            index.js
    container/
        main/
        profile/
        app.js
    style/
    lib/
        string.js
webpack.config.js

其中的:

/src/components/header/index.js

之前的,麻烦的写法是:

import {extractSingleStr} from “../../lib/string”;
import SwitchCowfarm from ‘../../components/switch-cowfarm’;

(1)resolve.modules中添加对应的路径,则可以使得import时省去对应路径

如果webpack.config.js中定义了resolve的modules,加上了src文件夹的话:

  resolve: {
    extensions: [‘.jsx’, ‘.js’, ‘.json’, ‘.less’],
    modules: [
      path.resolve(__dirname, “node_modules”),
      path.resolve(__dirname, “src”)
    ],

那么就可以改为:

import {extractSingleStr} from “lib/string”;
import SwitchCowfarm from ‘components/switch-cowfarm’;

其中的:

lib/string

components/switch-cowfarm

都可以正确解析是因为,loader会从resolve的modules中的src文件夹中能找到:

项目根目录/src/lib/string

项目根目录/src/components/switch-cowfarm

对应着,如果没有定义resolve的modules中的src的话,则会报错:

ERROR in ./src/components/header/index.js
Module not found: Error: Can’t resolve ‘lib/string’ in ‘/Users/crifan/dev/dev_root/daryun/Projects/xxxsourcecode/ucowsapp/ucowsapp/src/components/header’
@ ./src/components/header/index.js 14:14-35
@ ./src/container/app.js
@ ./src/index.js
@ multi (webpack)-dev-server/client?http://localhost:8080 webpack/hot/dev-server babel-polyfill ./index.js
ERROR in ./src/components/header/index.js
Module not found: Error: Can’t resolve ‘components/switch-cowfarm’ in ‘/Users/crifan/dev/dev_root/daryun/Projects/xxx/sourcecode/ucowsapp/ucowsapp/src/components/header’
@ ./src/components/header/index.js 16:21-57
@ ./src/container/app.js
@ ./src/index.js
@ multi (webpack)-dev-server/client?http://localhost:8080 webpack/hot/dev-server babel-polyfill ./index.js

(2)resolve.alias可以定义文件夹的别名,后续import时直接使用文件夹别名即可简化导入路径

比如定义了:

  resolve: {
    extensions: [‘.jsx’, ‘.js’, ‘.json’, ‘.less’],
    。。。
    alias: {
      ComponentsAlias: path.resolve(__dirname, “src/components”),
      LibAlias: path.resolve(__dirname, “src/lib”),

则之前的代码可以改为:

import {extractSingleStr} from “LibAlias/string”;
import SwitchCowfarm from ‘ComponentsAlias/switch-cowfarm’;

同样的,如果我此处不定义别名:

  resolve: {
    alias: {
        // StyleAlias: path.resolve(__dirname, “src/style”),

则代码:

// @import ‘~style/helpers’;
@import ‘~StyleAlias/helpers’;

会报错说无法解析:

ERROR in ./~/css-loader?{“modules”:true,”sourceMap”:true,”importLoaders”:1}!./~/postcss-loader/lib?{“sourceMap”:true}!./~/less-loader/dist/cjs.js?{“sourceMap”:true}!./src/components/header/style.less
Module build failed:
// @import ‘~style/helpers’;
@import ‘~StyleAlias/helpers’;
^
Can’t resolve ‘StyleAlias/helpers.less’ in ‘/Users/crifan/dev/dev_root/daryun/Projects/xxx/sourcecode/ucowsapp/ucowsapp/src/components/header’
      in /Users/crifan/dev/dev_root/daryun/Projects/xxx/sourcecode/ucowsapp/ucowsapp/src/components/header/style.less (line 2, column 0)
@ ./src/components/header/style.less 4:14-207 18:2-22:4 19:20-213
@ ./src/components/header/index.js
@ ./src/container/app.js
@ ./src/index.js
@ multi (webpack)-dev-server/client?http://localhost:8080 webpack/hot/dev-server babel-polyfill ./index.js

另外:

对于上述的:

@import ‘~StyleAlias/helpers’;

相关配置:

  resolve: {
    extensions: [‘.jsx’, ‘.js’, ‘.json’, ‘.less’],
    modules: [
      path.resolve(__dirname, “node_modules”),
      path.resolve(__dirname, “src”)
    ],
    alias: {
      StyleAlias: path.resolve(__dirname, “src/style”),
    }
  },

其实对应着3个含义:

(1)~:表示通过resolve.modules定义的文件夹(此处对应着src和node_modules)

(2)StyleAlias:对应着此处的resolve.alias中的

(3)此处src/style下面有helpers.less,省略了后缀是通过:resolve.extensions的定义:

StyleAlias: path.resolve(__dirname, “src/style”)

所以对应着:src/style文件夹

所以:

@import ‘~StyleAlias/helpers’;

翻译过来就是:

从此处resolve.modules定义的src和node_modules去找对应的src/style/helpers.less文件。

【后记】

貌似NODE_PATH可以实现类似的效果:

后来,看到:

How to Structure Your React Project

通过:

“start”: “cross-env NODE_PATH=src react-scripts start”,
“test”: “cross-env NODE_PATH=src react-scripts test –env=jsdom”,

和:

甚至:

NODE_PATH=src:src/components:src/containers

然后可以实现类似的效果:

把:

import Thing from ‘../../components/Thing’

改为:

import Thing from ‘components/Thing’
// or even
import Thing from ‘Thing’

以后有空也去试试这个效果。

总之,感觉是:

可以借用NODE_PATH去实现类似于Webpack的resolve.alias的效果。

转载请注明:在路上 » 【已解决】ReactJS中的@import路径中~波浪线的含义和通过resolve的alias简化导入路径

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
89 queries in 0.174 seconds, using 22.16MB memory