gpt4 book ai didi

javascript - 利用 webpack resolve/loader 添加后备

转载 作者:行者123 更新时间:2023-11-30 09:17:07 26 4
gpt4 key购买 nike

我有一个 React 应用程序(学生门户)。

我的文件夹结构如下:

\- build
- webpack.config.js
\- src
- App.js
- components\
- Login\
- Login.scss
- Login.js
- Dashboard\
- Register\
- redux\
- helpers\

我的 webpack 非常标准。

 var path = require('path');
var webpack = require('webpack');
module.exports = {
entry: './src/app.js',
output: {
path: path.resolve(__dirname, 'build'),
filename: 'app.bundle.js'
},
module: {
loaders: [
{
test: /\.js$/,
loader: 'babel-loader',
query: {
presets: ['es2015']
}
}
]
},
stats: {
colors: true
},
devtool: 'source-map'
};

我想在此应用程序之上构建。所以我将这个应用程序发布到 npm(本地)。我的文件夹结构现在是:

\- node_modules
- student-portal\
\ - src\
\ - build\

我想要的是能够替换/扩展现有组件,而不必复制现有文件。

所以,如果我创建一个新文件,我希望 webpack 使用它。如果这个文件不存在,它应该查看 node_modules/student-portal\src

所以 webpack 应该首先查看 src 文件,然后再查看 node_modules\student-portal\src

我尝试创建一个解析器函数:

var MyResolver = {
apply: function(resolver) {
resolver.plugin('module', function(request, callback) {
console.log(request.request); // this only consoles node_modules not .js files
});
}
};


但这并不能控制 .js 文件。我还尝试过许多其他插件,如 NormalModuleReplacementPlugin、ResolverPlugin 等,但都没有成功。

如果文件不存在,任何关于我如何利用 webpack 解析和替换路径的指示将不胜感激。理想情况下,我想扩展现有组件并让 webpack 将旧组件的路径替换为新组件的路径。

最佳答案

我想你可以使用 resolve.modules选项,因为它会按照您的描述进行操作。但是,由于问题是关于 resolve 插件的,所以我也会尝试编写一个。

解析模块

这是一个以 lodash 作为目标模块的例子。我们可以设置这样的结构:

node_modules
`--lodash
src
|--lodash
| `-- zip.js
`-index.js

zip.js 可以像 export default () => 'local zip'

在我们的 webpack.config.js 中,做

module.exports = {
...
resolve: {
modules: [path.resolve(__dirname, 'src'), 'node_modules'],
},
...
}

在我们的 index.js 中,让我们导入 zipisObject

// src/index.js
import zip from 'lodash/zip';
import isObject from 'lodash/isObject';

console.log(zip()); // 'local zip'
console.log(isObject({ a: 100 })); // 'true'

这基本上就是您想要的,但您不是编写自定义组件的相对路径,而是编写模块路径。

解析插件

但既然问题问的是插件,那就试试看吧!我之前评论过你的问题,但后来发现插件系统在 webpack 4 中发生了变化。我在节点 v10 上,所以一些语法在旧版本中可能不起作用。

目录结构:

node_modules
`--lodash
src
|--components
| `-- zip.js
`-index.js

首先,快速浏览一下解析插件。 Webpack 允许我们在解析管道(you can see the full list here)中使用多个钩子(Hook)。我们对 resolveparsedResolvemodule 特别感兴趣。我们的计划是:

1. Tap into the `resolve` hook  
2. Is the resolve request points to our 'components' folder?
- If not, go to **step 3**.
- If yes, is there something there it can use?
- If not, point it to `lodash` module instead.
- If yes, go to **step 3**.
3. Continue to the next hook in the pipeline (`parsedResolve`).

当我们点击一​​个钩子(Hook)时,我们会得到一个非常有用的 request 对象,其中包含这些属性:

  • context:包含发行者(index.js 的绝对路径)
  • path:发布者的目录(src的绝对路径)
  • request: 请求字符串('./components/zip')

有了它,我们就可以编写我们的插件了:

const path = require('path');
const fs = require('fs');

class CustomResolverPlugin {
constructor ({ dir, moduleName }) {
this.dir = dir; // absolute path to our 'components' folder
this.moduleName = moduleName; // name of the module, 'lodash' in this case
}
apply(resolver) {
resolver.getHook('resolve').tapAsync('CustomResolverPlugin', (request, resolveContext, callback) => {

// 1. check if the request is point to our component folder
// resolver.join is same as path.join, but memoized
const { dir } = path.parse(resolver.join(request.path, request.request));
const match = dir === this.dir;

if (match) {

// 2. get the name of the file being requested & check if it exists.
// in import zip from `./src/components/zip`, 'zip' is the name.
const { name } = path.parse(request.request);
const pathExist = fs.existsSync(path.join(this.dir, `${name}`));
if (!pathExist) {

// create a new request object.
// we'll swap the request to something like 'lodash/zip'
const _request = {
...request,
request: `${this.moduleName}/${name}`
}
// swap the target hook to 'module' to resolve it as a module.
const _target = resolver.ensureHook('module');
return resolver.doResolve(_target, _request, null, resolveContext, callback);
}
}

// 3. otherwise continue to the next hook
const target = resolver.ensureHook('parsedResolve');
return resolver.doResolve(target, request, null, resolveContext, callback);
});
}
}

webpack.config.js中的用法

module.exports = {
...
resolve: {
plugins: [
new CustomResolverPlugin({
dir: path.resolve(__dirname, './src/components'),
moduleName: 'lodash',
}),
],
},
...
}

在你的 index.js 中:

import zip from './components/zip';
import isObject from './components/isObject';

console.log(zip(['a', 'b'], [1, 2])); // 'local zip'
console.log(isObject({ a: 100 })); // true

希望对您有所帮助!

关于javascript - 利用 webpack resolve/loader 添加后备,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54320025/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com