如何在 ES6+ 的 webpack 中的 node_modules 上使用 babel 加载器?

Posted

技术标签:

【中文标题】如何在 ES6+ 的 webpack 中的 node_modules 上使用 babel 加载器?【英文标题】:How to use babel loader on node_modules in webpack for ES6+? 【发布时间】:2018-05-18 16:07:05 【问题描述】:

我有一个 react 项目,所有的扩展都是 .js,没有一个使用 .jsx。我下载了一个新库 react-pdf-js-infinite,它使用 .jsx。在我的 webpack 中,加载器作为异常运行在所有 node_modules 上。如何设置它以便它在我的 node_module 中的 .jsx 文件上运行。当我尝试使用 webpack 运行我的生产构建时,我经常遇到错误。说这个文件可能需要一个加载器,并且当构建遇到组件类中静态 propTypes 的 ecma 标准时。任何帮助将不胜感激。

class PDF extends Component 
  static propTypes = 
    x: propType.String
  

【问题讨论】:

【参考方案1】:

这就是你的 webpack 配置的样子。这包含所有加载器 ES6 与 React redux Sass 和其他实用程序。

/* eslint-env node */
const autoprefixer = require('autoprefixer');
const CompressionPlugin = require('compression-webpack-plugin');
const path = require('path');
const webpack = require('webpack');
const htmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const SystemBellPlugin = require('system-bell-webpack-plugin');
var CopyWebpackPlugin = require('copy-webpack-plugin');

const highlightjsLanguages=['javascript', 'python', 'bash', 'java', 'cpp'];

const env=process.env.NODE_ENV;
const isProd = (env.toLowerCase().trim() === 'production')? true: false;
const vendor = [
      'react',
      'react-dom',
      'react-router-dom',
      'prop-types',
      'redux',
      'react-redux',
      'redux-thunk',
      'axios',
      'babel-polyfill',
      'browser-detect'
      ];
// Configuration object
const config = 
  devtool: isProd ? 'source-map' : 'source-map',
  entry: ['babel-polyfill','./src/index'],
  output: 
    path: path.resolve(__dirname, 'dist'),
    filename: isProd ? '[name].[chunkhash].js' : 'bundle.js',
    publicPath: '/',
  ,
  resolve: 
    extensions: ['*', '.js', '.jsx', '.json'],
  ,
  target: 'web',
  module: 
    rules: [
      
        enforce: 'pre',
        test: /\.jsx?$/,
        exclude: /node_modules/,
        loader: 'eslint-loader',
      ,
      
        test: /\.jsx?$/,
        exclude: /node_modules/,
        loader: 'babel-loader',
      ,
      
        test: /\.(css|scss|sass)$/,
        exclude: /node_modules/,
        use: ExtractTextPlugin.extract(
          fallback: 'style-loader',
          use: [
            loader: 'css-loader',
            options: 
              sourceMap: true,
            ,
          , 
            loader: 'postcss-loader',
            options: 
              sourceMap: true,
              plugins() 
                return [autoprefixer('last 2 versions', 'ie 10')];
              ,
            ,
          , 
            loader: 'sass-loader',
            options:  sourceMap: true ,
          ],
        ),
      ,
       test: /\.eot(\?v=\d+.\d+.\d+)?$/, loader: 'file-loader?name=assests/fonts/[name].[ext]' ,
       test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: 'file-loader?mimetype=application/font-woff&name=assests/fonts/[name].[ext]' ,
       test: /\.[ot]tf(\?v=\d+.\d+.\d+)?$/, loader: 'file-loader?mimetype=application/octet-stream&name=assests/fonts/[name].[ext]' ,
       test: /\.svg(\?v=\d+.\d+.\d+)?$/, loader: 'file-loader?mimetype=image/svg+xml&name=assests/fonts/[name].[ext]' ,
       test: /\.(jpe?g|png|gif|ico)$/i, loader: 'file-loader?name=assests/images/[name].[ext]' ,
    ],
  ,
  devServer: 
    contentBase: path.resolve(__dirname, 'dist'),
    compress: true,
    port: 8000,
    historyApiFallback: true,
    hot: true
  ,
  plugins: [
    new webpack.NoEmitOnErrorsPlugin(),
    new ExtractTextPlugin(
      filename: '[name].[contenthash].css',
      disable: !isProd,
    ),
    new webpack.DefinePlugin(
      'process.env': 
        NODE_ENV: JSON.stringify(process.env.NODE_ENV),
      ,
    ),
    new SystemBellPlugin(),
    new CopyWebpackPlugin( [from:'src/web.config',to:'./']),
    new webpack.ContextReplacementPlugin(
      /highlight\.js\/lib\/languages$/,
      new RegExp(`^./($highlightjsLanguages.join('|'))$`)
    )
  ],
;

if (isProd) 
  Array.prototype.push.apply(config.plugins, [
    new webpack.optimize.UglifyJsPlugin(
      mangle: true,
      compress: 
        warnings: false, // Suppress uglification warnings
        pure_getters: true,
        unsafe: true,
        unsafe_comps: true,
        screw_ie8: true
      ,
      output: 
        comments: false,
      ,
      exclude: [/\.min\.js$/gi] // skip pre-minified libs
      ),
    new webpack.optimize.OccurrenceOrderPlugin(),
    new webpack.optimize.AggressiveMergingPlugin(),
    new webpack.optimize.CommonsChunkPlugin(
      name: 'vendors',
      minChunks(module) 
        const  context  = module;
        if (typeof context !== 'string') 
          return false;
        
        return context.indexOf('node_modules') !== -1;
      ,
    ),
    new webpack.optimize.CommonsChunkPlugin(
      name: 'common',
      minChunks(module, count) 
        return count >= 2;
      ,
    ),
    new webpack.optimize.CommonsChunkPlugin(
      name: 'runtime'
    ),
    new CompressionPlugin(
      asset: '[path].gz[query]',
      algorithm: 'gzip',
      test: /\.(js|html)$/,
      threshold: 10240,
      minRatio: 0.8,
    ),
    new webpack.LoaderOptionsPlugin(
      minimize: true,
      debug: false,
      noInfo: true,
      options: 
        context: './',
      ,
    ),
    new HtmlWebpackPlugin(
      title: 'KM Q&A',
      filename: 'index.html',
      template: './src/index.ejs',
      favicon: './src/favicon.ico',
      minify: 
        removeComments: true,
        collapseWhitespace: true,
        removeRedundantAttributes: true,
        useShortDoctype: true,
        removeEmptyAttributes: true,
        removeStyleLinkTypeAttributes: true,
        keepClosingSlash: true,
        minifyJS: true,
        minifyCSS: true,
        minifyURLs: true,
      ,
      inject: true,
    ),
    new webpack.optimize.ModuleConcatenationPlugin(),
    new webpack.HashedModuleIdsPlugin()
  ]);
 else 
  config.entry.splice(1, 0, 'react-hot-loader/patch');
  Array.prototype.push.apply(config.plugins, [
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NamedModulesPlugin(),
    new HtmlWebpackPlugin(
      title: 'KM Q&A',
      filename: 'index.html',
      template: './src/index.ejs',
      inject: true,
      favicon: './src/favicon.ico',
    ),
    new webpack.LoaderOptionsPlugin(
      minimize: false,
      debug: true,
      noInfo: false,
      options: 
        context: './',
      ,
    ),
  ]);



module.exports = config;

这应该是你的 .babelrc 文件


  "presets": [
    [
      "env",
       "modules": false ],
    "react"
    ],
    "plugins": [
      "react-hot-loader/babel",
      "transform-object-rest-spread",
      "transform-class-properties"
    ],
  "env":
    "test":
      "presets": [
        "env",
        "react"
    ],
    "plugins": [
      "transform-object-rest-spread",
      "transform-class-properties"
    ]
  

这是带有 Jest 测试的基本 packages.json


  "name": "react-starter",
  "version": "1.0.0",
  "main": "index.jsx",
  "scripts": 
    "start": "set NODE_ENV=development&& npm-run-all --parallel open:dev lint:watch npm:lock",
    "prebuild": "npm run remove-dist && mkdir dist",
    "build:prod": "set NODE_ENV=production&& webpack",
    "build:dev": "set NODE_ENV=development&& webpack",
    "lint": " esw src --color",
    "lint:watch": "npm run lint --watch",
    "open:dev": "webpack-dev-server",
    "open:dist": "http-server ./dist -p 8081 -s -o",
    "remove-dist": "rimraf ./dist",
    "npm:lock": "npm shrinkwrap",
    "test:dev": "set NODE_ENV=test&&Set TEST_ENV=development&&jest -u",
    "test:prod": "set NODE_ENV=test&&Set TEST_ENV=production&&jest -u",
    "coverage:dev": "set NODE_ENV=test&&Set TEST_ENV=development&&jest --coverage",
    "coverage:prod": "set NODE_ENV=test&&Set TEST_ENV=production&&",
    "installmodules": "npm install",
  ,
  "license": "MIT",
  "dependencies": 
    "axios": "^0.17.1",
    "babel-polyfill": "^6.26.0",
    "detect-browser": "^2.0.0",
    "font-awesome": "^4.7.0",
    "prop-types": "^15.6.0",
    "raf": "^3.4.0",
    "react": "^16.1.1",
    "react-dom": "^16.1.1",
    "react-hot-loader": "^3.1.3",
    "react-redux": "^5.0.6",
    "react-router-dom": "^4.2.2",
    "redux": "^3.7.2",
    "redux-thunk": "^2.2.0"
  ,
  "devDependencies": 
    "autoprefixer": "^7.1.6",
    "axios-mock-adapter": "^1.10.0",
    "babel-core": "^6.26.0",
    "babel-eslint": "^8.0.1",
    "babel-jest": "^21.2.0",
    "babel-loader": "^7.1.2",
    "babel-plugin-transform-class-properties": "^6.24.1",
    "babel-plugin-transform-object-rest-spread": "^6.26.0",
    "babel-preset-env": "^1.6.1",
    "babel-preset-react": "^6.24.1",
    "compression-webpack-plugin": "^1.0.1",
    "copy-webpack-plugin": "^4.2.0",
    "css-loader": "^0.28.7",
    "enzyme": "^3.2.0",
    "enzyme-adapter-react-16": "^1.1.0",
    "eslint": "^4.10.0",
    "eslint-config-airbnb": "^16.1.0",
    "eslint-loader": "^1.9.0",
    "eslint-plugin-import": "^2.8.0",
    "eslint-plugin-jsx-a11y": "^6.0.2",
    "eslint-plugin-react": "^7.4.0",
    "eslint-watch": "^3.1.3",
    "extract-text-webpack-plugin": "^3.0.1",
    "file-loader": "^1.1.5",
    "html-webpack-plugin": "^2.30.1",
    "http-server": "^0.10.0",
    "jest": "^21.2.1",
    "node-sass": "^4.6.1",
    "npm-run-all": "^4.1.1",
    "postcss-loader": "^2.0.8",
    "react-addons-perf": "^15.4.2",
    "react-test-renderer": "^16.1.1",
    "redux-mock-store": "^1.3.0",
    "sass-loader": "^6.0.6",
    "sinon": "^4.1.2",
    "style-loader": "^0.19.0",
    "system-bell-webpack-plugin": "^1.0.0",
    "webpack": "^3.8.1",
    "webpack-dev-server": "^2.9.4"
  ,
  "optionalDependencies": 
    "bufferutil": "^3.0.3"
  ,
  "jest": 
    "moduleNameMapper": 
      "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js",
      "\\.(css|scss)$": "<rootDir>/__mocks__/styleMock.js"
    ,
    "automock": false,
    "transform": 
      "^.+\\.jsx?$": "<rootDir>/node_modules/babel-jest",
      "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/__mocks__/fileMock.js"
    ,
    "moduleFileExtensions": [
      "js",
      "jsx"
    ],
    "moduleDirectories": [
      "node_modules"
    ],
    "unmockedModulePathPatterns": [
      "<rootDir>/node_modules/react/",
      "<rootDir>/node_modules/react-dom/"
    ],
    "transformIgnorePatterns": [
      "/node_modules/"
    ],
    "coveragePathIgnorePatterns": [
      "/node_modules/"
    ],
    "modulePathIgnorePatterns": [
      "/node_modules/"
    ],
    "collectCoverage": true,
    "coverageReporters": [
      "json",
      "lcov",
      "text"
    ]
  

【讨论】:

我知道这个问题是 4 年前的问题,但我仍然有点震惊,因为这两个答案都没有解决了 OP 所问的问题——那就是他想要处理 node_modules 中的文件。这两个都特别排除 node_modules 被转换,这正是OP不想要的

以上是关于如何在 ES6+ 的 webpack 中的 node_modules 上使用 babel 加载器?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 webpack.config.js 中使用 ES6?

如何使用 React + ES6 + webpack 导入和导出组件?

反应,流星,webpack,es6。如何创建加载/启动屏幕

如何在webpack.config.js中使用ES6?

如何在 webpack 中同时使用 ES6 加载器和 brfs 转换?

如何优化 webpack/es6 开销?