为啥 webpack4 生产包总是包含 style-loader、css-loader 和 vue-loader 内容?

Posted

技术标签:

【中文标题】为啥 webpack4 生产包总是包含 style-loader、css-loader 和 vue-loader 内容?【英文标题】:why webpack4 production bundle will always include style-loader, css-loader and vue-loader content?为什么 webpack4 生产包总是包含 style-loader、css-loader 和 vue-loader 内容? 【发布时间】:2019-04-15 16:11:58 【问题描述】:

在 webpack 中使用生产模式构建的多入口点最终捆绑包中导出的多入口编译 js 文件始终包含加载程序内容。如何消除它们以及为什么包含它们?

复制

git clone https://github.com/adamchenwei/boilerplate-webpack-babel-sass-storybook-vuejs.git
git checkout step/3-prod-webpack-build-setup-basic
npm install
npm run build:prod

任何想法将不胜感激。 https://webpack.js.org/plugins/module-concatenation-plugin/ 也没有帮助。 我读了几个 SO 似乎还没有解决方案。

谢谢

webpack.common.js

const path = require('path');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const htmlWebpackPlugin = require('html-webpack-plugin');

function resolve (dir) 
  return path.join(__dirname, '..', dir)

module.exports = 
  entry: 
    app: './src/library.js',
    HelloComp: './src/components/HelloComponent/HelloComponent.vue',
    Bye: './src/components/ByeComponent/ByeComponent.vue'
  ,
  plugins: [
    new CleanWebpackPlugin(['dist']),
    new HtmlWebpackPlugin(
      title: 'Production'
    )
  ],
  output: 
    filename: '[name].js',
    path: path.resolve(__dirname, 'dist')
  ,
  externals: 
    'vue': 
      root: 'vue',
      commonjs2: 'vue',
      commonjs: 'vue',
      amd: 'vue',
      umd: 'vue'
    ,
    'vue-router': 
      root: 'vue-router',
      commonjs2: 'vue-router',
      commonjs: 'vue-router',
      amd: 'vue-router',
      umd: 'vue-router'
    ,
    'style-loader': 
      root: 'style-loader',
      commonjs2: 'style-loader',
      commonjs: 'style-loader',
      amd: 'style-loader',
      umd: 'style-loader'
    ,
    'vue-hot-reload-api': 
      root: 'vue-hot-reload-api',
      commonjs2: 'vue-hot-reload-api',
      commonjs: 'vue-hot-reload-api',
      amd: 'vue-hot-reload-api',
      umd: 'vue-hot-reload-api'
    ,
    'vue-loader': 
      root: 'vue-loader',
      commonjs2: 'vue-loader',
      commonjs: 'vue-loader',
      amd: 'vue-loader',
      umd: 'vue-loader'
    
  

webpack.prod.js

const merge = require('webpack-merge');
const common = require('./webpack.common.js');
const webpack = require('webpack')
const  VueLoaderPlugin  = require('vue-loader')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
// const path = require('path')
// function resolve (dir) 
//   return path.join(__dirname, '..', dir)
// 

const configedAnalyzer = new BundleAnalyzerPlugin(
  // Can be `server`, `static` or `disabled`.
  // In `server` mode analyzer will start HTTP server to show bundle report.
  // In `static` mode single HTML file with bundle report will be generated.
  // In `disabled` mode you can use this plugin to just generate Webpack Stats JSON file by setting `generateStatsFile` to `true`.
  analyzerMode: 'static',
  // Host that will be used in `server` mode to start HTTP server.
  analyzerHost: '127.0.0.1',
  // Port that will be used in `server` mode to start HTTP server.
  analyzerPort: 8887,
  // Path to bundle report file that will be generated in `static` mode.
  // Relative to bundles output directory.
  reportFilename: './../report/bundle_anlaysis.html',
  // Module sizes to show in report by default.
  // Should be one of `stat`, `parsed` or `gzip`.
  // See "Definitions" section for more information.
  defaultSizes: 'gzip',
  // Automatically open report in default browser
  openAnalyzer: true,
  // If `true`, Webpack Stats JSON file will be generated in bundles output directory
  generateStatsFile: true,
  // Name of Webpack Stats JSON file that will be generated if `generateStatsFile` is `true`.
  // Relative to bundles output directory.
  statsFilename: 'stats.json',
  // Options for `stats.toJson()` method.
  // For example you can exclude sources of your modules
  // from stats file with `source: false` option.
  // See more options here: https://github.com/webpack/webpack/blob/webpack-1/lib/Stats.js#L21
  statsOptions: null,
  // Log level. Can be 'info', 'warn', 'error' or 'silent'.
  logLevel: 'info'
)

module.exports = merge(common, 
  mode: 'production',
  module: 
    rules: [
      
        test: /\.vue$/,
        use: 'vue-loader'
      ,
      // IMPORTANT: All js load should come AFTER vue-loader!!!
      
        test: /\.(js|vue)$/,
        use: 'eslint-loader',
        enforce: 'pre' // kick in before other loader... Q: also before vue-loader I suppose? maybe better move it to top?
      ,
      
        test: /\.css$/,
        use: [
          'vue-style-loader',
          'css-loader'
        ]
      ,
      
        test: /\.scss$/,
        use: [
          'style-loader', // creates style nodes from JS strings
          'css-loader', // translates CSS into CommonJS
          'sass-loader' // compiles Sass to CSS, using Node Sass by default
        ]
      ,
      
        test: /\.js$/,
        use: 'babel-loader'
      
    ]
  ,
  plugins: [
    new webpack.HotModuleReplacementPlugin(),
    new VueLoaderPlugin(),
    new HtmlWebpackPlugin(
      filename: 'index.html',
      template: 'index.html',
      inject: true
    ),
    new CopyWebpackPlugin([
      // NOTE: it does not really do anything, unless we have a asset folder, that needed no compression
      from: './static/',
      to: './static/',
      toType: 'dir'
    ]),

    // NOTE: honestly, this did not help reduce prod bundle size... but for wtw:
    // https://webpack.js.org/plugins/module-concatenation-plugin/
    new webpack.optimize.ModuleConcatenationPlugin(),

    // NOTE: disable when needed, its just to analyze code
    configedAnalyzer
  ],
  stats: 
    // Examine all modules
    maxModules: Infinity,
    // Display bailout reasons
    optimizationBailout: true
  
);

【问题讨论】:

发布您的配置。 @PlayMa256 它在我的仓库中,但我还是粘贴了,给你! 【参考方案1】:

从你的外部移除 style-loader 并确保从你的 css 生成实际的 css 文件......否则 webpack 必须以某种方式插入你的样式,对吗?

要做到这一点,请使用mini-css-extract-plugin

 
        test: /\.css$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader'
        ]
      ,
      
        test: /\.scss$/,
        use: [
          MiniCssExtractPlugin.loader,
          'css-loader', // translates CSS into CommonJS
          'sass-loader' // compiles Sass to CSS, using Node Sass by default
        ]
    

不要忘记将new MiniCssExtractPlugin() 也添加到您的插件中。仅适用于生产构建。

【讨论】:

它似乎构建成功,但是当我尝试导入另一个 vue ap 时,组件出现[Vue warn]: Unknown custom element: <mini-c> - did you register the component correctly? For recursive components, make sure to provide the "name" option. while I do have name defined as MiniC` 错误。有什么想法吗? 要尝试它,你必须运行github.com/adamchenwei/vue-dependency-demo 我不是 vue 专家,对此我无能为力。但这里的关键问题是,在生产环境中 webpack 必须使用 style-loader 将样式放入页面中,这就是原因。尝试使用 vue 添加 mini-css-extract-plugin。 嘿,np,是的,解决了主要问题,我遇到的问题是处理 Vuejs 的奇怪组件命名约定......非常感谢!

以上是关于为啥 webpack4 生产包总是包含 style-loader、css-loader 和 vue-loader 内容?的主要内容,如果未能解决你的问题,请参考以下文章

为啥RNN总是输出1

为啥应用程序包不总是一个包?

webpack系列从零搭建 webpack4+react 脚手架

为啥我的 python 总是运行另一个包的文件

NSIS做的安装包为啥路径总是C盘呢?

为啥 UIBarButtonItem 图像总是模糊/模糊/像素化