Node JS 服务器代码中的 Webpack 别名

Posted

技术标签:

【中文标题】Node JS 服务器代码中的 Webpack 别名【英文标题】:Webpack Aliases in Node JS Server code 【发布时间】:2016-04-13 12:39:46 【问题描述】:

我正在构建一个同构的 React/React-Router/Redux/Webpack 应用程序,并且我正在尝试实现服务器端渲染。

我的目录如下:

/client
    /actions
    /components
    /containers
/server
    /server.js

在我的 webpack 配置中,我为客户端内的所有文件夹设置了别名:

var path_base = path.resolve(__dirname, '..');
const resolve = path.resolve;
const base = function() 
  var args = [path_base];
  args.push.apply(args, arguments);
  return resolve.apply(resolve,args);
;
const resolve_alias = base.bind(null, 'src/client');
const aliases = [
  'actions',
  'components',
  'constants',
  'containers',
  'middleware',
  'reducers',
  'routes',
  'store',
  'styles',
  'utils',
  'validation'
];

这样在被 webpack 捆绑的代码中,我可以这样做:

import  Widget  from 'components'; 

并且该导入由 webpack 解决。

现在在我的服务器代码中,为了进行渲染,我必须导入一些客户端文件,例如 routes/index.js。我在导入路由文件时遇到的问题,它使用 webpack 别名到另一个文件,比如 componentscontainers 所以很自然,节点 js 要求系统无法解决它。

我该如何解决这样的问题?我查看了this question,它谈到了使用mock-require 设置webpack 中存在的相同别名。但是问题就变成了我的路由文件导入了我的所有组件,然后所有组件都导入了样式表、图像等内容。然后我应该使用webpack-isomorphic-tools之类的东西吗?

我一直在看的指南(例如this)都很好地展示了如何完成服务器端渲染,但没有一个真正谈论如何解决所有需求等等。

【问题讨论】:

听起来这里有几个问题:(a)在运行服务器端时如何使用别名,以及(b)如何在服务器上处理包含的资源,如样式表。一种解决方案是也通过 webpack 运行您的服务器代码。您可以在配置中使用target: node,它会在构建期间针对节点优化它(即它不会捆绑节点包含)。我有时会为使用 Babel 的代码执行此操作。如果不进行构建,绝对不要使用别名。任何解决方案充其量都是hacky。 为什么我不能使用别名? 使用 webpack 进行 build 时,别名很好。您的问题是因为您在 webpack 构建中使用别名并试图让相同的代码在 outside webpack 构建中工作。我的观点是,要使用别名,您还需要构建服务器代码(这将使别名正常工作)。如果没有构建,让别名起作用的唯一方法是将它组合在一起,这就是您的问题所在。黑客是不好的,所以使用别名并构建你的服务器代码,或者干脆放弃别名。 那么使用 webpack-isomorphic-tools 之类的东西应该不成问题,因为它支持服务器和客户端代码的别名。 gist.github.com/startupthekid/3223a866616b6dc59e4d5d4fc03275a7。我包含了我的别名文件、所有配置,然后是我的 package.json 中的脚本。有很多文件,服务器和客户端各有四个(基本配置、开发配置、生产配置、生产入口文件和开发入口文件),然后是一个基本配置文件以及通用 webpack 配置文件。我没有把它们都放在要点里(我还没有设置生产配置),但这对你来说应该是一个好的开始 【参考方案1】:

在与这个问题斗争了 2 天后,我选择了 babel-plugin-webpack-alias。 What you need to do 解析路径是:

    $ npm install --save-dev babel-plugin-webpack-alias 将插件添加到您的 .babelrc 中 将别名添加到您的 webpack.config(确保使用 path.join()) 如果您在加载样式时遇到问题,请参阅this post

我尝试的另一个选项是universal-webpack,但我发现它有点冗长。如果你想大致了解整个服务器端加载是如何工作的,可以查看this video。

【讨论】:

babel-plugin-webpack-alias 有效,但似乎打破了 Jest。将此插件隔离到 Babel 的 development 环境(通过 env 配置键)为我解决了这个问题【参考方案2】:

如果你真的想要它们,通过 babel 运行你的服务器端代码并​​使用这个插件:https://www.npmjs.com/package/babel-plugin-module-alias 它可以让你做和 webpack 一样的事情。

编辑:这个效果更好:https://github.com/jagrem/babel-resolve-relative-module 它允许多条路径

【讨论】:

不使用它们的原因是什么? 这似乎会导致问题,而且您必须依赖至少在服务器上使用一个插件,并且可能通过 Babel 运行您的整个代码库。我想这很好,但如果你引入 Babel 的唯一原因是为了别名,那似乎需要做很多工作 感谢您链接到那个 Babel 插件!我没想过要在 Babel 方面寻找混叠。这对我帮助很大!【参考方案3】:

尝试使用NODE_PATH。在 require 调用期间,Node 将始终在此路径中查找模块。它允许根据需要缩短相对路径。

// turn this
import Widget from '../../components';

// into this
import Widget from 'components';

更多信息请参见Node.js docs。

附注这东西很敏感,所以要小心使用。现在您的代码与环境紧密相关,可能会在某处中断。

【讨论】:

【参考方案4】:

如果您使用 webpack-isomorphic-tools,那么它会将您的 webpack 配置考虑到您的服务器端,这将使您的所有别名都工作。

https://www.npmjs.com/package/webpack-isomorphic-tools

【讨论】:

以上是关于Node JS 服务器代码中的 Webpack 别名的主要内容,如果未能解决你的问题,请参考以下文章

Node.js / npm / yarn / Vue / webpack 概念介绍

72.vue开发工具node.js以及构建工具webpack

无法访问我的站点中的链接(复制和粘贴):Node.js - Express.js - Webpack - Vue.js - 历史模式

第562期用 webpack 构建 node 后端代码,使其支持 js 新特性并实现热重载

Node.js - 在 Server.js 上执行 Node 命令(Express + React + Webpack)

nodemon 没有在 webpack-typescript-node.js 中监视目录?