【问题标题】:How to stop webpack from creating dist/main.js after upgrade to Webpack 5?升级到 Webpack 5 后如何阻止 webpack 创建 dist/main.js?
【发布时间】:2021-08-25 21:39:35
【问题描述】:

我正在将 Webpack 与 Elixir/Phoenix 一起使用。我最近从 Webpack 4 升级到了 Webpack 5。

我认为一切正常,除了现在由于某种原因在我运行测试时总是在项目根dist/main.js 创建一个 dist 和 main.js。这个文件大部分是空的:

/*
 * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
 * This devtool is neither made for production nor for readable output files.
 * It uses "eval()" calls to create a separate source file in the browser devtools.
 * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
 * or disable the default devtool with "devtool: false".
 * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
 */
/******/ (() => { // webpackBootstrap
/******/    "use strict";
/******/    
/******/    
/******/ })()
;

在我的 mix.exs 中,我有以下内容。这是创建dist/main.js的代码行

  defp compile_assets(_) do
    Mix.shell().cmd("./assets/node_modules/webpack/bin/webpack.js --mode development",
      quiet: false
    )
  end

我的 webpack.config 包括:

    devtool: 'eval-source-map',
    entry: {
      'app': glob.sync('./vendor/**/*.js').concat(['./js/app.js']),
      'marketing': glob.sync('./vendor/**/*.js').concat(['./js/marketing.js']),
      'admin': glob.sync('./vendor/**/*.js').concat(['./js/admin.js']),
    },
    output: {
      filename: '[name].js',
      path: path.resolve(__dirname, '../priv/static/js')
    },

当我在 IEx 中运行它时,我得到:

iex(1)> Mix.shell().cmd("./assets/node_modules/webpack/bin/webpack.js --mode development", quiet: false)
asset main.js 662 bytes [emitted] (name: main)

ERROR in main
Module not found: Error: Can't resolve './src' in '/Users/me/development/apps/my_app'
resolve './src' in '/Users/me/development/apps/my_app'
  No description file found in /Users/me/development/apps/my_app or above
  No description file found in /Users/me/development/apps/my_app or above
  no extension
    /Users/me/development/apps/my_app/src doesn't exist
  .js
    /Users/me/development/apps/my_app/src.js doesn't exist
  .json
    /Users/me/development/apps/my_app/src.json doesn't exist
  .wasm
    /Users/me/development/apps/my_app/src.wasm doesn't exist
  as directory
    /Users/me/development/apps/my_app/src doesn't exist

webpack 5.50.0 compiled with 1 error in 50 ms
1

由于我已经指定了条目,我认为它应该没问题。任何帮助将不胜感激。

更新: 显示整个 webpack.config.js

const path = require('path');
const glob = require('glob');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const CopyWebpackPlugin = require('copy-webpack-plugin');
const { VueLoaderPlugin } = require('vue-loader');
const webpack = require('webpack')
const Dotenv = require('dotenv-webpack');

module.exports = (webpackEnv, webpackOptions) => {

  const platform = process.env.PLATFORM
  if (platform == undefined) {
    throw "process.env.PLATFORM is undefined!"
  }
  dotEnvFile = `.env.${platform}`
  const mode = platform === 'production' ? 'production' : 'development';
  const minimize = platform === 'production' ? true : false;
  const cache = platform === 'production' ? false : { type: 'filesystem' };
  const vueProdDevtools = platform === 'production' ? false : true;

  return {
    cache: cache,
    mode: mode,
    optimization: {
      minimize: minimize,
      minimizer: [
        new TerserPlugin({
          parallel: true
        }),
        new CssMinimizerPlugin()
      ]
    },
    entry: {
      'app': glob.sync('./vendor/**/*.js').concat(['./js/app.js']),
      'marketing': glob.sync('./vendor/**/*.js').concat(['./js/marketing.js']),
      'admin': glob.sync('./vendor/**/*.js').concat(['./js/admin.js']),
    },
    output: {
      filename: '[name].js',
      path: path.resolve(__dirname, '../priv/static/js')
    },
    module: {
      rules: [
        {
          test: /\.vue$/,
          use: [
            {
              loader: 'vue-loader',
              options: {
                compilerOptions: {
                  compatConfig: {
                    MODE: 2
                  }
                }
              }
            }
          ]
        },      {
          test: /\.js$/,
          exclude: /node_modules/,
          use: [
            {
              loader: 'babel-loader'
            }
          ]
        },
        {
          test: /\.css$/,
          use: [
            MiniCssExtractPlugin.loader,
            'css-loader',
            'postcss-loader'
          ]
        },
        {
          test: /\.scss$/,
          use: [
            'vue-style-loader',
            'css-loader',
            'sass-loader'
          ]
        }
      ]
    },
    plugins: [
      new Dotenv({
        path: path.resolve(__dirname, '..', dotEnvFile)
      }),
      new MiniCssExtractPlugin({ filename: '../css/[name].css' }),
      new CopyWebpackPlugin({patterns:[{ from: 'static/', to: '../' }]}),
      new VueLoaderPlugin(),
      new webpack.DefinePlugin({
        __VUE_PROD_DEVTOOLS__: vueProdDevtools
      })
    ],
    resolve: {
      alias: {
        vue: '@vue/compat'
      },
      extensions: [ '*', '.js', '.vue', '.json' ],
    },
  }
};

更新 2:

根据将文件名转换为函数的建议,我将其更新为:

    output: {
      filename: (pathData, assetInfo) => {
        console.log("******** pathData:", pathData)
        console.log("******** assetInfo:", assetInfo)

        return '[name].js'
      },
      path: path.resolve(__dirname, '../priv/static/js')
    }

有趣的是当我跑步时

mix phx.server

输出是:

******** pathData: {
  hash: '449eeaf77670741a6887',
  runtime: 'app',
  chunk: Chunk {
    id: 'app',
    ids: [ 'app' ],
    debugId: 1000,
    name: 'app',
    idNameHints: SortableSet [Set] {
      _sortFn: undefined,
      _lastActiveSortFn: Symbol(not sorted),
      _cache: undefined,
      _cacheOrderIndependent: undefined
    },
    preventIntegration: false,
    filenameTemplate: undefined,
    _groups: SortableSet [Set] {
      [Entrypoint],
      _sortFn: [Function: compareChunkGroupsByIndex],
      _lastActiveSortFn: Symbol(not sorted),
      _cache: undefined,
      _cacheOrderIndependent: undefined
    },
    runtime: 'app',
    files: SetDeprecatedArray [Set] { '../css/app.css' },
    auxiliaryFiles: Set {},
    rendered: false,
    hash: '09da590258e85092531ee1a26f184db4',
    contentHash: [Object: null prototype] {
      'css/mini-extract': '4500f8bd1df6d9d548c3',
      javascript: 'a1a060a5ddfcebc58653'
    },
    renderedHash: '09da590258e85092531e',
    chunkReason: undefined,
    extraAsync: false
  },
  contentHashType: 'javascript'
}
******** assetInfo: {}
******** pathData: {
  hash: '449eeaf77670741a6887',
  runtime: 'marketing',
  chunk: Chunk {
    id: 'marketing',
    ids: [ 'marketing' ],
    debugId: 1001,
    name: 'marketing',
    idNameHints: SortableSet [Set] {
      _sortFn: undefined,
      _lastActiveSortFn: Symbol(not sorted),
      _cache: undefined,
      _cacheOrderIndependent: undefined
    },
    preventIntegration: false,
    filenameTemplate: undefined,
    _groups: SortableSet [Set] {
      [Entrypoint],
      _sortFn: [Function: compareChunkGroupsByIndex],
      _lastActiveSortFn: Symbol(not sorted),
      _cache: undefined,
      _cacheOrderIndependent: undefined
    },
    runtime: 'marketing',
    files: SetDeprecatedArray [Set] { '../css/marketing.css' },
    auxiliaryFiles: Set {},
    rendered: false,
    hash: 'e11f89b04d9e2d62877069c780bfd99c',
    contentHash: [Object: null prototype] {
      'css/mini-extract': '1218451d2cf9d01e4c35',
      javascript: '0bf8255fc0482a761bba'
    },
    renderedHash: 'e11f89b04d9e2d628770',
    chunkReason: undefined,
    extraAsync: false
  },
  contentHashType: 'javascript'
}
******** assetInfo: {}
******** pathData: {
  hash: '449eeaf77670741a6887',
  runtime: 'admin',
  chunk: Chunk {
    id: 'admin',
    ids: [ 'admin' ],
    debugId: 1002,
    name: 'admin',
    idNameHints: SortableSet [Set] {
      _sortFn: undefined,
      _lastActiveSortFn: Symbol(not sorted),
      _cache: undefined,
      _cacheOrderIndependent: undefined
    },
    preventIntegration: false,
    filenameTemplate: undefined,
    _groups: SortableSet [Set] {
      [Entrypoint],
      _sortFn: [Function: compareChunkGroupsByIndex],
      _lastActiveSortFn: Symbol(not sorted),
      _cache: undefined,
      _cacheOrderIndependent: undefined
    },
    runtime: 'admin',
    files: SetDeprecatedArray [Set] { '../css/admin.css' },
    auxiliaryFiles: Set {},
    rendered: false,
    hash: '6a55d7e6d1cc37be6087e1c464285cc2',
    contentHash: [Object: null prototype] {
      'css/mini-extract': '613df220ea4099b5fbf5',
      javascript: '90a7803cefe86244fd07'
    },
    renderedHash: '6a55d7e6d1cc37be6087',
    chunkReason: undefined,
    extraAsync: false
  },
  contentHashType: 'javascript'
}
******** assetInfo: {}

所以,我看到它为每个入口点运行一次(有道理)。但是,当我在 IEx 中时:

Interactive Elixir (1.12.2) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> Mix.shell().cmd("./assets/node_modules/webpack/bin/webpack.js --mode development", quiet: false)
asset main.js 662 bytes [compared for emit] (name: main)

ERROR in main
Module not found: Error: Can't resolve './src' in '/Users/me/development/apps/my_app'
resolve './src' in '/Users/me/development/apps/my_app'
  No description file found in /Users/me/development/apps/my_app or above
  No description file found in /Users/me/development/apps/my_app or above
  no extension
    /Users/me/development/apps/my_app/src doesn't exist
  .js
    /Users/me/development/apps/my_app/src.js doesn't exist
  .json
    /Users/me/development/apps/my_app/src.json doesn't exist
  .wasm
    /Users/me/development/apps/my_app/src.wasm doesn't exist
  as directory
    /Users/me/development/apps/my_app/src doesn't exist

webpack 5.51.1 compiled with 1 error in 47 ms
1

所以console.log 命令不在IEx 中打印。这可能有关系吗?可能是测试代码正在运行的命令,IEx 中的命令,正在运行“不同”的 webpack 命令?是不是找不到 webpack.config?

【问题讨论】:

  • 你能分享你的整个 webpack 配置吗?很可能你在 webpack 配置文件中返回了一些空的东西。
  • @Wenbo 我添加了整个 webpack.config.js
  • 如何将output下的filename改成函数,然后在函数中设置断点进行诊断。函数可以像``` filename: (path) => { console.log("**** path: ",path, " name: ", [name]); }, ```
  • @Wenbo 很好的建议。我用输出更新了问题。这有什么想法吗?
  • @Wenbo 您能否通过建议与compile_assets 函数相关的问题来回答这个问题,因为该问题仅针对该场景出现。错误消息意味着 webpack 没有找到 webpack 配置。 ./assets/node_modules/webpack/bin/webpack.js 可能有问题。我会给你赏金。

标签: javascript webpack bundle phoenix-framework


【解决方案1】:

创建 dist/main.js 的原因是因为 webpack 运行时找不到 webpack.config.js,所以 dist/main.js 是默认行为。

当我将filename 更新为一个函数时,我发现了这一点。然后我在其中打电话给console.log("test") 并希望在IEx 中看到它。控制台日志从未打印出来。

然后我运行常规的mix phx.server,我确实得到了新的输出。

dev.exs 中有:

    watchers: [
      node: [
        "node_modules/webpack/bin/webpack.js",
        "--mode",
        "development",
        "--progress",
        "--watch",
        "--watch-options-stdin",
        cd: Path.expand("../assets", __DIR__)
      ]
    ]

这一切看起来都符合预期,但实现方式不同。 (它使用的是cd: Path.expand,但我现在才注意到这一点。)

那么,为什么一个不工作而另一个很好呢?

仔细观察

  defp compile_assets(_) do
    Mix.shell().cmd("./assets/node_modules/webpack/bin/webpack.js --mode development",
      quiet: false
    )
  end

我决定看看我是从哪里得到这个的(来自 Wallaby 文档)

我回到文档并注意到它已经改变了。

变化如下: https://github.com/elixir-wallaby/wallaby/commit/834bdb726228349f800837e470a0c77cd2f4a6bd

现在代码应该是:

  defp compile_assets(_) do
    Mix.shell().cmd("cd assets && ./node_modules/.bin/webpack --mode development",
      quiet: true
    )

我不知道为什么我们需要 cd into assets 而不是我们以前拥有的,但现在它可以工作了。

【讨论】:

    猜你喜欢
    • 2021-04-29
    • 2020-08-06
    • 1970-01-01
    • 2021-05-22
    • 1970-01-01
    • 1970-01-01
    • 2018-01-14
    • 1970-01-01
    • 2022-01-13
    相关资源
    最近更新 更多