首页 > 解决方案 > 模块构建失败:UnhandledSchemeError:从“别名:/路径”读取不是由插件处理(未处理的方案)

问题描述

我正在创建一个新的反应应用程序并尝试从头开始配置 webpack 编译器。使用以下命令运行构建命令时会出现此问题webpack -c config/webpack.config.ts- 它给出如下错误;

ERROR in containers:/App
Module build failed: UnhandledSchemeError: Reading from "containers:/App" is not handled by plugins (Unhandled scheme).
Webpack supports "data:" and "file:" URIs by default.
You may need an additional plugin to handle "containers:" URIs.
    at /home/myuser/dev/projects/tsxpress-boilerplate/node_modules/webpack/lib/NormalModule.js:659:26
    at Hook.eval [as callAsync] (eval at create (/home/myuser/dev/projects/tsxpress-boilerplate/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:6:1)
    at Hook.CALL_ASYNC_DELEGATE [as _callAsync] (/home/myuser/dev/projects/tsxpress-boilerplate/node_modules/tapable/lib/Hook.js:18:14)
    at Object.processResource (/home/myuser/dev/projects/tsxpress-boilerplate/node_modules/webpack/lib/NormalModule.js:656:9)
    at processResource (/home/myuser/dev/projects/tsxpress-boilerplate/node_modules/loader-runner/lib/LoaderRunner.js:220:11)
    at iteratePitchingLoaders (/home/myuser/dev/projects/tsxpress-boilerplate/node_modules/loader-runner/lib/LoaderRunner.js:171:10)
    at runLoaders (/home/myuser/dev/projects/tsxpress-boilerplate/node_modules/loader-runner/lib/LoaderRunner.js:397:2)
    at NormalModule.doBuild (/home/myuser/dev/projects/tsxpress-boilerplate/node_modules/webpack/lib/NormalModule.js:646:3)
    at NormalModule.build (/home/myuser/dev/projects/tsxpress-boilerplate/node_modules/webpack/lib/NormalModule.js:791:15)
    at /home/myuser/dev/projects/tsxpress-boilerplate/node_modules/webpack/lib/Compilation.js:1239:12
 @ ./client/app/index.tsx 12:28-54

知道是什么导致了这个或我错过了什么吗?任何建议表示赞赏。


我的目录结构如下:

node_modules/
client/
  public/
  app/
    assets/
    index.tsx
server/
shared/
  http/
  models/
  state/
  utils/
build/
config/
  webpack.config.js

文件index.tsx

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { Router, BrowserRouter } from 'react-router-dom';
import { createBrowserHistory } from 'history';
import { store } from 'shared:/states/store';
import App from 'containers:/App';

const history = createBrowserHistory();

ReactDOM.render(
  <Provider store={store}>
    <Router history={history}>
      <BrowserRouter>
        <App />
      </BrowserRouter>
    </Router>
  </Provider>,
  document.getElementById('app')
);

文件tsconfig.json/compilerOptions/paths

  "paths": {
    "shared:/*": ["shared/*"],
    "containers:/*": ["client/app/views/containers/*"],
  }

文件webpack.config.js

resolve: {
  modules: paths.clientAppModules,
  extensions: ['.tsx', '.ts', '.js'],
  alias: {
    'shared:': '/home/myuser/dev/projects/tsxpress-boilerplate/shared',
    'containers:': '/home/myuser/dev/projects/tsxpress-boilerplate/client/app/views/containers'
  }
},

依赖项:

请让我知道您需要更多详细信息;

标签: reactjstypescriptwebpackwebpack-5

解决方案


看这里https://github.com/webpack/webpack/pull/11095/files

https://github.com/vankop/webpack/blob/7bbc2aa3ceb34d93b6f17549f02eca3518d680d2/lib/index.js#L433

https://github.com/vankop/webpack/blob/7bbc2aa3ceb34d93b6f17549f02eca3518d680d2/lib/schemes/FileUriPlugin.js#L25

您缺少的是 webpack 不支持“http”或“file”以外的方案。错误消息是这样说的。

import { store } from 'shared:/states/store';
import App from 'containers:/App';

shared并且containers不是支持的方案,webpack 不会将它们转发给 babel/typescript,所以这种 URI 不起作用。

除非,你愿意写一个旁路插件,我虽然有人已经做了一个,但我只发现了这个错误。复制文件插件并添加更多方案似乎很容易,这就是我要做的。

[编辑:] 在 Webpack5 中,您可以例如:

就这样做吧。

"use strict";

const node_url = require("url");

class AnySchemeUriPlugin {

    constructor(options = {}) {
        this.options = options;
    }

    apply(compiler) {
        compiler.hooks.compilation.tap(
            "AnySchemeUriPlugin",
            (compilation, { normalModuleFactory }) => {
                Array.from(this.options.schemes).forEach(scheme => {
                    normalModuleFactory.hooks.resolveForScheme
                        .for(scheme)
                        .tap("AnySchemeUriPlugin", resourceData => {
                            const uri = resourceData.resource.replace(`${scheme}://`, 'file://');
                            const url = new node_url.URL(uri);
                            const path = node_url.fileURLToPath(url);
                            const query = url.search;
                            const fragment = url.hash;
                            resourceData.path = path;
                            resourceData.query = query;
                            resourceData.fragment = fragment;
                            resourceData.resource = path + query + fragment;
                            return true;
                        });
                });
            }
        );
    }
}

module.exports = AnySchemeUriPlugin;

那么,在你的webpack.config


    // The HtmlWebpackPlugin allows us to use a template for the index.html page
    // and automatically injects <script> or <link> tags for generated bundles.
    const commonPlugins = [
        new HtmlWebpackPlugin({
            filename: 'index.html',
            template: baseConfig.indexHtmlTemplate,
            inlineSource: '^.+\.(css)$',
        }),
        new AnySchemeUriPlugin({
            schemes: ['ssr']
        })
        //new BundleAnalyzerPlugin(),
    ];

    return {
        entry: {
            app: [
                baseConfig.fsharpEntry
            ],
        },
        context: baseConfig.srcDir,
        plugins: isProduction
            ? commonPlugins.concat([
            ]) : commonPlugins,
     }

推荐阅读