之前在折腾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
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一致:
提到了说是:
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.”
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简化导入路径