ES6 从根导入

ES6 import from root

我目前正在研究 React Native。我正在尝试构建我的应用程序,但它开始因导入而变得混乱。

--app/
    -- /components
        -- Loading.js
    -- index.ios.js

现在,在我的 index.ios.js 中,我可以简单地做到:

import Loading from './components/Loading';

然而,当我开始创建更多组件时,具有更深的目录结构,它开始变得混乱:

import Loading from '.../../../../components/Loading';

我知道首选的解决方案是为事物制作私有 npm 模块,但这对于小项目来说太过分了。

您可以在浏览器上执行 global.requireRoot 类型的解决方案,但我如何使用导入实现它?

与 React 有同样的问题。 所以我为 babel 写了一些插件,可以从根视角导入模块——路径并不短——但很清楚你导入的是什么。

所以代替:

import 'foo' from '../../../components/foo.js';

您可以使用:

import 'foo' from '~/components/foo.js';

Here is the Plugin (tested and with a clear README)

如果您使用的是 Webpack,您可以通过 resolve 属性 配置它来解析您的导入路径。

Webpack 1

resolve: {
  root: [
    path.resolve(__dirname  + '/src')
  ]
}......

Webpack 2

resolve: {
  modules: [
    path.resolve(__dirname + '/src'),
    path.resolve(__dirname + '/node_modules')
  ]
}.....

之后你可以使用

import configureStore from "store/configureStore";

而不是:

import configureStore from "../../store/configureStore";

Webpack 将从传递的解析参数配置您的导入路径。

你可以用 System.js 加载器做同样的事情,但它有自己的配置参数(它可以是 mappath。在 System.js 文档中检查它)(如果你想使用它。它主要用于 Angular 2 案例。但我建议:不要使用标准 System.js 即使你正在使用 ng2。Webpack 好多了)。

使用 webpack,您还可以将以 ~ 开头的路径解析为根目录,因此您可以使用 import Loading from '~/components/Loading';:

resolve: {
  extensions: ['.js'],
  modules: [
    'node_modules', 
    path.resolve(__dirname + '/app')
  ],
  alias: {
    ['~']: path.resolve(__dirname + '/app')
  }
}

诀窍是使用 javascript 括号语法来分配 属性.

Webpack 3 中,配置略有不同:

import webpack from 'webpack';
import {resolve} from 'path';

...

module: {
    loaders: [
        {
            test: /\.js$/,
            use: ["babel-loader"]
        },
        {
            test: /\.scss$|\.css$/,
            use: ["style-loader", "css-loader", "sass-loader"]
        }
    ]
},
resolve: {
    extensions: [".js"],
    alias: {
        ["~"]: resolve(__dirname, "src")
    }
},

我刚刚检查了一个超过 6 个月的 React 项目,由于某些原因我的导入不再有效。我尝试了第一个答案:

import 'foo' from '~/components/foo.js';

不幸的是,这没有用。

我在项目的根目录中添加了一个 .env 文件,与 package.json 处于同一级别。我在该文件中添加了以下行,这修复了我在项目中的导入。

NODE_PATH=src/

如果您使用的是 Create React App,您可以在 config/webpack.config.dev.jsconfig/webpack.config.prod.js.

中将 paths.appSrc 添加到 resolve.modules

发件人:

resolve: {
    modules: ['node_modules', paths.appNodeModules].concat(...

收件人:

resolve: {
    modules: [paths.appSrc, 'node_modules', paths.appNodeModules].concat(...

您的代码将可以运行:

import Loading from 'components/Loading';

如果您使用 Create-React-App, you just need to change the environmental variable NODE_PATH 来包含项目的根目录。

在您的 config.json 中进行以下更改以在 运行 反应脚本命令之前设置此变量:

"scripts": {
  "start": "cross-env NODE_PATH=. react-scripts start",
  "build": "cross-env NODE_PATH=. react-scripts build",
  "test": "cross-env NODE_PATH=. react-scripts test",
  "eject": "react-scripts eject"
},

我们正在使用 npm 库 cross-env 因为它适用于 unix 和 windows。语法是 cross-env var=value command.

现在我们可以 import module from 'src/my/module'

而不是 import module from '../../my/module'

实施的额外细节

重要的是要注意 cross-env 的范围仅限于它执行的命令,因此 cross-env var=val command1 && command2 只会在 command1 期间设置 var。如果需要,可以通过 cross-env var=val command1 && cross-env var=val command2

来解决这个问题

create-react-app 优先于 node_modules/ 中的文件夹,而不是 NODE_PATH 中的文件夹,这就是我们将 NODE_PATH 设置为“.”的原因。而不是“./src”。使用 ”。”要求所有绝对导入以 "src/" 开头,这意味着永远不会有名称冲突,除非您使用一些 node_module 称为 src.

(注意事项:上面描述的解决方案 替换了 变量 NODE_PATH。理想情况下,如果它已经存在,我们将附加到它。 NODE_PATH 是一个“:”或“;”分隔的路径列表,具体取决于它是 unix 还是 windows。如果有人找到跨平台解决方案来执行此操作,我可以编辑我的答案。)

反应文档解释了如何做到这一点: https://create-react-app.dev/docs/importing-a-component/#absolute-imports

只需在您的项目根目录中添加一个jsconfig.json:

{
   "compilerOptions": {
      "baseUrl": "src"
   },
  "include": ["src"]
}