Knex: Erros "Módulo não encontrado" ao usar knex com webpack

Criado em 6 jan. 2016  ·  23Comentários  ·  Fonte: knex/knex

Estou tentando usar o knex em um projeto em que estou trabalhando. O problema que estou tendo é que, quando tento executar o webpack, ele está rastreando os requisitos e tentando extrair drivers/dialetos que não estou usando e não tenho instalados.

Alguma ideia de como isso pode ser resolvido?

`````` log
ERRO em ./~/mariasql/lib/Client.js
Módulo não encontrado: Erro: Não é possível resolver 'arquivo' ou 'diretório' ../build/Debug/sqlclient em ~/project/node_modules/mariasql/lib
@ ./~/mariasql/lib/Client.js 17:10-45

ERRO em ./~/knex/lib/dialects/sqlite3/index.js
Módulo não encontrado: Erro: Não é possível resolver o módulo 'sqlite3' em ~/project/node_modules/knex/lib/dialects/sqlite3
@ ./~/knex/lib/dialects/sqlite3/index.js 33:11-29

ERRO em ./~/knex/lib/dialects/mysql2/index.js
Módulo não encontrado: Erro: Não é possível resolver o módulo 'mysql2' em ~/project/node_modules/knex/lib/dialects/mysql2
@ ./~/knex/lib/dialects/mysql2/index.js 33:11-28

ERRO em ./~/knex/lib/dialects/mysql/index.js
Módulo não encontrado: Erro: Não é possível resolver o módulo 'mysql' em ~/project/node_modules/knex/lib/dialects/mysql
@ ./~/knex/lib/dialects/mysql/index.js 35:11-27

ERRO em ./~/knex/lib/dialects/oracle/index.js
Módulo não encontrado: Erro: Não é possível resolver o módulo 'oracle' em ~/project/node_modules/knex/lib/dialects/oracle
@ ./~/knex/lib/dialects/oracle/index.js 40:11-28

ERRO em ./~/knex/lib/dialects/postgres/index.js
Módulo não encontrado: Erro: Não é possível resolver o módulo 'pg' em ~/project/node_modules/knex/lib/dialects/postgres
@ ./~/knex/lib/dialects/postgres/index.js 46:11-24

ERRO em ./~/knex/lib/dialects/postgres/index.js
Módulo não encontrado: Erro: Não é possível resolver o módulo 'pg-query-stream' em ~/project/node_modules/knex/lib/dialects/postgres
@ ./~/knex/lib/dialects/postgres/index.js 132:50-76

ERRO em ./~/knex/lib/dialects/strong-oracle/index.js
Módulo não encontrado: Erro: Não é possível resolver o módulo 'strong-oracle' em ~/project/node_modules/knex/lib/dialects/strong-oracle
@ ./~/knex/lib/dialects/strong-oracle/index.js 15:9-33```
``````

Comentários muito úteis

também se deparou com isso. o que funciona para mim;

externals: {
  knex: 'commonjs knex'
}

Todos 23 comentários

Eu tive esse problema, mas adicionar um Regex aos meus externos na configuração do meu webpack corrigiu:

const commonLoaders = [
  { test: /\.js$/, loader: 'babel', exclude: [/node_modules/] },
  { test: /\.json$/, loader: 'json' },
];

module.exports = [
  {
    name: 'browser',
    entry: './js/entry.js',
    output: {
      path: './build',
      filename: 'bundle.js',
    },
    module: {
      loaders: commonLoaders.concat([
        { test: /\.styl$/, loader: 'style!css!stylus' },
      ]),
    },
  },
  {
    name: 'server',
    entry: './server.js',
    target: 'node',
    output: {
      path: './build',
      filename: 'server.js',
      libraryTarget: 'commonjs2',
    },
    externals: [
      {
        'socket.io': 'socket.io',
      },
      /^[a-z\-0-9]+$/,
    ],
    module: {
      loaders: commonLoaders.concat([
        { test: /\.styl$/, loader: 'css!stylus' },
      ]),
    },
  },
];

+1

@joeketchi Ignorar o diretório node_modules realmente não resolve o problema, estamos apenas resolvendo o problema. Seria incrível se o código fizesse esses requisitos de uma maneira mais inteligente que não gerasse erros.

Também correu para isso. Não tenho certeza por que ignorar node_modules não funciona.

também se deparou com isso. o que funciona para mim;

externals: {
  knex: 'commonjs knex'
}

Não posso comentar especificamente sobre o problema do mariasql mas o que resolveu meu problema é definir todos os drivers que não uso como externos. Por exemplo, eu uso o driver mysql2 para o meu projeto, então tenho isso em externos:

  externals: {
    // Possible drivers for knex - we'll ignore them
    'sqlite3': 'sqlite3',
    'mariasql': 'mariasql',
    'mssql': 'mssql',
    'mysql': 'mysql',
    'oracle': 'oracle',
    'strong-oracle': 'strong-oracle',
    'oracledb': 'oracledb',
    'pg': 'pg',
    'pg-query-stream': 'pg-query-stream'
  }

O resultado é que o knex é empacotado sem erros ou avisos

Este problema parece ser apenas um problema de como configurar a configuração do webpack ao incluir o knex... vamos reabrir se houver alterações necessárias no knex para suportar melhor o webpack.

Na verdade, não acho que o assunto deva ser encerrado ainda, ainda existem problemas não resolvidos com o webpack, com migração e semente:

WARNING in ./node_modules/knex/lib/migrate/index.js
342:20-81 Critical dependency: the request of a dependency is an expression

WARNING in ./node_modules/knex/lib/migrate/index.js
447:18-49 Critical dependency: the request of a dependency is an expression

WARNING in ./node_modules/knex/lib/seed/index.js
113:13-74 Critical dependency: the request of a dependency is an expression

WARNING in ./node_modules/knex/lib/seed/index.js
150:11-24 Critical dependency: the request of a dependency is an expression

não consegui consertar isso

@ifullgaz isso não parece ser um erro, mas apenas um aviso de que require() não foi usado com literal de string? https://github.com/webpack/webpack/issues/196

@ifullgaz , tentei sua solução, mas recebi erros como abaixo. Você se deparou com um problema semelhante?

  Error --------------------------------------------------
  Command failed: npm install
gyp ERR! UNCAUGHT EXCEPTION
gyp ERR! stack Error: spawn EACCES
gyp ERR! stack     at exports._errnoException (util.js:1018:11)
gyp ERR! stack     at ChildProcess.spawn (internal/child_process.js:319:11)
gyp ERR! stack     at exports.spawn (child_process.js:378:9)
gyp ERR! stack     at exports.execFile (child_process.js:143:15)

@brianhuangyl você corrigiu a propriedade etc. para o diretório node_modules e todo o conteúdo ist (você não executou o npm install como root em nenhum momento)?

     [EACCES]       Permission bits of the file mode do not permit the
            requested access, or search permission is denied on a
            component of the path prefix.

@ifullgaz encontrei a sugestão de https://www.laurivan.com/make-electron-work-with-knex-js/ corrigi esses erros:

WARNING in ./node_modules/knex/lib/migrate/index.js
342:20-81 Critical dependency: the request of a dependency is an expression

WARNING in ./node_modules/knex/lib/migrate/index.js
447:18-49 Critical dependency: the request of a dependency is an expression

WARNING in ./node_modules/knex/lib/seed/index.js
113:13-74 Critical dependency: the request of a dependency is an expression

WARNING in ./node_modules/knex/lib/seed/index.js
150:11-24 Critical dependency: the request of a dependency is an expression

Especificamente, esta parte funcionou para mim:

config.plugins = [
  // ...
  new NormalModuleReplacementPlugin(/\.\.\/migrate/, '../util/noop.js'),
  new NormalModuleReplacementPlugin(/\.\.\/seed/, '../util/noop.js'),
];

este foi o bilhete para mim libraryTarget: 'commonjs2',

Eu procurei uma abordagem um pouco diferente que permite que o webpack processe a maioria das instruções require nos arquivos knex, mas deixará os require s não literais sozinhos para que os arquivos de migração e semente fornecidos pelo usuário da biblioteca seja encontrado. Aqui está a abordagem que fiz:

config.module.rules = [
  {
    include: [
      /knex\/lib\/migrate\/index/,
      /knex\/lib\/seed\/index/
    ],
    loader: 'string-replace-loader',
    options: {
      search: 'require(\\([^\'"])',
      replace: '__non_webpack_require__$1',
      flags: 'g'
    }
  }
];

Oi pessoal, eu estava trabalhando para resolver o problema de criar um pacote webpack completo para um serviço usando knex e me deparei com esse problema ao tentar executar migrações programaticamente desse pacote. A sugestão de @mdlavin fez com que ele executasse o require, mas resultou no webpack não transformando o arquivo de origem. Isso também significava que eu precisaria incluir esse diretório com o pacote fora de banda do pacote webpack.

Eu descobri que você pode usar ContextReplacementPlugin do webpack para resolver o problema com migrações e sementes. Abaixo está uma amostra da minha configuração (escrito em texto datilografado):

plugins: [
  //...
  fs.existsSync(path.join(params.targetPackageFilePath, 'migrations')) && new webpack.ContextReplacementPlugin(
    /knex\/lib\/migrate/,
    '.',
    fs.readdirSync(path.join(params.targetPackageFilePath, 'migrations'))
      .reduce((result, file) => {
        return Object.assign(result, {
          [path.join(params.targetPackageFilePath, 'migrations', file)]: path.relative(
            path.dirname(require.resolve('knex/lib/migrate')),
            path.join(params.targetPackageFilePath, 'migrations', file)
          )
        });
      }, {})),

  fs.existsSync(path.join(params.targetPackageFilePath, 'seeds')) && new webpack.ContextReplacementPlugin(
    /knex\/lib\/seed/,
    '.',
    fs.readdirSync(path.join(params.targetPackageFilePath, 'seeds'))
      .reduce((result, file) => {
        return Object.assign(result, {
          [path.join(params.targetPackageFilePath, 'seeds', file)]: path.relative(
            path.dirname(require.resolve('knex/lib/seed')),
            path.join(params.targetPackageFilePath, 'seeds', file)
          )
        });
      }, {}))
  //...
]

Na minha configuração params.targetPackageFiletPath é o caminho resolvido para o pacote que está sendo compilado, por exemplo /Users/yourusername/yourproject . Portanto, se um projeto nesse caminho tiver os diretórios migrations e seeds , as configurações de plug-in resultantes seriam algo assim:

  fs.existsSync(path.join(params.targetPackageFilePath, 'migrations')) && new webpack.ContextReplacementPlugin(
    /knex\/lib\/migrate/,
    '.',
    {
      '/Users/yourusername/yourproject/201706261234_migration.ts': '../../../migrations/201706261234_migration.ts'
    }),

  fs.existsSync(path.join(params.targetPackageFilePath, 'seeds')) && new webpack.ContextReplacementPlugin(
    /knex\/lib\/seed/,
    '.',
    {
      '/Users/yourusername/yourproject/seeds/201706261234_first-seed.ts': '../../../seeds/201706261234_first-seed.ts'
    }),

Para detalhar um pouco, o problema é que o código de migração e semente do knex chama require para carregar suas migrações e sementes, como faz aqui https://github.com/tgriesser/knex/blob/master/ src/migrate/index.js#L54. Ele passa o resultado de uma função/expressão para exigir sem prefixo ou sufixo de string codificado, portanto, quando o webpack tenta descobrir quais arquivos podem realmente carregar, ele não tem informações suficientes para determinar isso. Esses plugins fornecem as informações necessárias ao webpack.

Não tenho certeza se o Knex pode ser alterado para torná-los desnecessários ao agrupar com o webpack. Talvez fazendo os requisitos na terra do usuário?

De qualquer forma, pensei em compartilhar uma solução que funcionou para mim.

Alguma sugestão para este problema em Angular?
Eu tento usar o projeto expresso, é normal (não mostra nenhum erro). Mas quando eu uso no projeto Angular, ele mostra o erro:

ERROR in ./node_modules/knex/lib/dialects/oracle/utils.js Module not found: Error: Can't resolve 'crypto' in '/Users/marudits/Documents/CODE/PROJECT/MOJOMARET/app-member/node_modules/knex/lib/dialects/oracle' ERROR in ./node_modules/knex/lib/dialects/mssql/index.js Module not found: Error: Can't resolve 'mssql/package.json' in '/Users/marudits/Documents/CODE/PROJECT/MOJOMARET/app-member/node_modules/knex/lib/dialects/mssql' ERROR in ./node_modules/knex/lib/runner.js Module not found: Error: Can't resolve 'stream' in '/Users/marudits/Documents/CODE/PROJECT/MOJOMARET/app-member/node_modules/knex/lib' ERROR in ./node_modules/knex/lib/dialects/oracledb/index.js Module not found: Error: Can't resolve 'stream' in '/Users/marudits/Documents/CODE/PROJECT/MOJOMARET/app-member/node_modules/knex/lib/dialects/oracledb'

onde posso fazer a configuração para remover esse erro?
poderia ser configurado no arquivo angular.json ou tsconfig.json ?

Provavelmente no webpack.

Isso corrigiu para mim (crédito a @ifullgaz ) Eu tive que adicionar mysql2.

    externals: {
        // Possible drivers for knex - we'll ignore them
        sqlite3: 'sqlite3',
        mysql2: 'mysql2',
        mariasql: 'mariasql',
        mysql: 'mysql',
        oracle: 'oracle',
        'strong-oracle': 'strong-oracle',
        oracledb: 'oracledb',
        pg: 'pg',
        'pg-query-stream': 'pg-query-stream'
    }

Em seguida, basta remover o driver que você está usando desta lista e o webpack o incluirá no arquivo build.

@ifullgaz encontrei a sugestão de https://www.laurivan.com/make-electron-work-with-knex-js/ corrigi esses erros:

WARNING in ./node_modules/knex/lib/migrate/index.js
342:20-81 Critical dependency: the request of a dependency is an expression

WARNING in ./node_modules/knex/lib/migrate/index.js
447:18-49 Critical dependency: the request of a dependency is an expression

WARNING in ./node_modules/knex/lib/seed/index.js
113:13-74 Critical dependency: the request of a dependency is an expression

WARNING in ./node_modules/knex/lib/seed/index.js
150:11-24 Critical dependency: the request of a dependency is an expression

Especificamente, esta parte funcionou para mim:

config.plugins = [
  // ...
  new NormalModuleReplacementPlugin(/\.\.\/migrate/, '../util/noop.js'),
  new NormalModuleReplacementPlugin(/\.\.\/seed/, '../util/noop.js'),
];

Isso funcionou muito bem para mim. Eu fiz isso:

plugins: [
    new webpack.NormalModuleReplacementPlugin(/m[sy]sql2?|oracle(db)?|sqlite3/, "node-noop"),
    new webpack.NormalModuleReplacementPlugin(/\.\.\/migrate/, "node-noop"),
    new webpack.NormalModuleReplacementPlugin(/\.\.\/seed/, "node-noop")
  ]

1) Não consegui fazer com que a importação relativa de noop.js funcionasse porque estava tentando importá-la profundamente dentro do knex. Acabei de instalar esta simples node-noop lib e funcionou bem.
2) Usamos o Postgres, então a regex na primeira linha corresponde a todas as outras que ela procura. Modifique para o conteúdo do seu coração.

2019/10 consegui fazer funcionar, veja minha resposta em outro problema https://github.com/tgriesser/knex/issues/1446#issuecomment -537715431

Eu coloquei a dependência pg como "externa" e resolveu o problema muito obrigado, isso significa que o webpack analisa as dependências de back-end?

Oi pessoal, eu estava trabalhando para resolver o problema de criar um pacote webpack completo para um serviço usando knex e me deparei com esse problema ao tentar executar migrações programaticamente desse pacote. A sugestão de @mdlavin fez com que ele executasse o require, mas resultou no webpack não transformando o arquivo de origem. Isso também significava que eu precisaria incluir esse diretório com o pacote fora de banda do pacote webpack.

Eu descobri que você pode usar ContextReplacementPlugin do webpack para resolver o problema com migrações e sementes. Abaixo está uma amostra da minha configuração (escrito em texto datilografado):

plugins: [
  //...
  fs.existsSync(path.join(params.targetPackageFilePath, 'migrations')) && new webpack.ContextReplacementPlugin(
    /knex\/lib\/migrate/,
    '.',
    fs.readdirSync(path.join(params.targetPackageFilePath, 'migrations'))
      .reduce((result, file) => {
        return Object.assign(result, {
          [path.join(params.targetPackageFilePath, 'migrations', file)]: path.relative(
            path.dirname(require.resolve('knex/lib/migrate')),
            path.join(params.targetPackageFilePath, 'migrations', file)
          )
        });
      }, {})),

  fs.existsSync(path.join(params.targetPackageFilePath, 'seeds')) && new webpack.ContextReplacementPlugin(
    /knex\/lib\/seed/,
    '.',
    fs.readdirSync(path.join(params.targetPackageFilePath, 'seeds'))
      .reduce((result, file) => {
        return Object.assign(result, {
          [path.join(params.targetPackageFilePath, 'seeds', file)]: path.relative(
            path.dirname(require.resolve('knex/lib/seed')),
            path.join(params.targetPackageFilePath, 'seeds', file)
          )
        });
      }, {}))
  //...
]

Na minha configuração params.targetPackageFiletPath é o caminho resolvido para o pacote que está sendo compilado, por exemplo /Users/yourusername/yourproject . Portanto, se um projeto nesse caminho tiver os diretórios migrations e seeds , as configurações de plug-in resultantes seriam algo assim:

  fs.existsSync(path.join(params.targetPackageFilePath, 'migrations')) && new webpack.ContextReplacementPlugin(
    /knex\/lib\/migrate/,
    '.',
    {
      '/Users/yourusername/yourproject/201706261234_migration.ts': '../../../migrations/201706261234_migration.ts'
    }),

  fs.existsSync(path.join(params.targetPackageFilePath, 'seeds')) && new webpack.ContextReplacementPlugin(
    /knex\/lib\/seed/,
    '.',
    {
      '/Users/yourusername/yourproject/seeds/201706261234_first-seed.ts': '../../../seeds/201706261234_first-seed.ts'
    }),

Para detalhar um pouco, o problema é que o código de migração e semente do knex chama require para carregar suas migrações e sementes, como faz aqui https://github.com/tgriesser/knex/blob/master/ src/migrate/index.js#L54. Ele passa o resultado de uma função/expressão para exigir sem prefixo ou sufixo de string codificado, portanto, quando o webpack tenta descobrir quais arquivos podem realmente carregar, ele não tem informações suficientes para determinar isso. Esses plugins fornecem as informações necessárias ao webpack.

Não tenho certeza se o Knex pode ser alterado para torná-los desnecessários ao agrupar com o webpack. Talvez fazendo os requisitos na terra do usuário?

De qualquer forma, pensei em compartilhar uma solução que funcionou para mim.

Salve meus dias, muito obrigado.

Para aqueles que procuram uma solução, esta funcionou para mim usando knex@^0.21.1, eu queria o driver mysql2 retido. Peguei 2 soluções existentes, que funcionaram juntas para mim.

Na configuração do webpack, mesclar em uma versão modificada de https://github.com/knex/knex/issues/1128#issuecomment -515573845

externals: [
      {
        // Possible drivers for knex - we'll ignore them
       // comment the one YOU WANT to use
        sqlite3: 'sqlite3',
        // mysql2: 'mysql2', // << using this one
        mariasql: 'mariasql',
        mysql: 'mysql',
        mssql: 'mssql',
        oracle: 'oracle',
        'strong-oracle': 'strong-oracle',
        oracledb: 'oracledb',
        pg: 'pg',
        'pg-query-stream': 'pg-query-stream',
      }

Adicione também um plug-in do webpack, que excluirá os pacotes ofensivos
ref https://github.com/knex/knex/issues/3130#issuecomment -573293311

Modifiquei o original para excluir corretamente no meu caso de uso, incluindo o conjunto correto de subdiretórios mssql e também para permitir alguns pacotes pg que são necessários para o Knex funcionar

    new webpack.IgnorePlugin(
        new RegExp('^(mssql*|mariasql|.oracle.|sqlite3|mssql/.*|tedious|node-pre-gyp)$')
      ),
Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

nklhrstv picture nklhrstv  ·  3Comentários

saurabhghewari picture saurabhghewari  ·  3Comentários

mishitpatel picture mishitpatel  ·  3Comentários

sandrocsimas picture sandrocsimas  ·  3Comentários

mtom55 picture mtom55  ·  3Comentários