webpack 2的react开发配置实例代码


Posted in Javascript onJuly 28, 2017

基于webpack 2.3的标准语法,包含了less变量替换、React组件热加载、第三库单独输出、区分生产与开发环境等常用配置。

'use strict'

module.exports = function( env ) {
  // 生成环境下webpack使用-p参数开启代码压缩
  // webpack[-dev-server]使用--env dev参数指定编译环境
  var isDev = env == 'dev';

  var path = require( 'path' );
  var webpack = require( 'webpack' );
  var CleanWebpackPlugin = require( 'clean-webpack-plugin' );
  var CopyWebpackPlugin = require( 'copy-webpack-plugin' );
  var HtmlWebpackPlugin = require( 'html-webpack-plugin' );
  var WebkitPrefixer = require( 'autoprefixer' );
  var WebpackMd5Hash = require( 'webpack-md5-hash' );
  var BundleAnalyzerPlugin = require( 'webpack-bundle-analyzer' ).BundleAnalyzerPlugin;

  var sourcedir = path.resolve( __dirname, 'src' );// 源码和资源文件的放置位置
  var outputdir = path.resolve( __dirname, 'build' );// 编译结果的放置位置
  var webContextRoot = '/myreact/';// 应用的实际访问路径,默认是'/'
  // antd的图标字体文件的实际访问路径,利用less-load的变量替换功能
  var antd_fonticon = webContextRoot + 'assets/antd_fonticon/iconfont';

  var hasValue = function( item ) { return item != null; };
  return {
    //context: path.resolve( __dirname ),
    devtool: 'source-map',
    devServer: {
      host: '0.0.0.0',
      port: 8082,
      historyApiFallback: true
    },
    resolve: {
      // 让less-loader等插件能找到以~相对定位的资源
      modules: [sourcedir, 'node_modules']
    },
    entry: {
      main: [
        // 编译新版本js的新api(如Promise),主要是让IE11能够执行编译后的代码
        'babel-polyfill',
        //使用react-hot-loader@3.0.0-beta.6,
        // 搭配webpack-dev-server --hot命令实现react组件的hot reload
        isDev ? 'react-hot-loader/patch' : null,
        path.resolve( sourcedir, 'main.jsx' )].filter( hasValue ),
      // 第三方库汇总输出
      vendor: ['bootstrap/dist/css/bootstrap.min.css', 'react',
        'react-dom', 'react-router', 'redux', 'react-redux',
        'react-router-redux', 'moment', 'lodash', 'immutable', 'whatwg-fetch',
        // 只含antd的js部分
        'antd',
        // 各控件还需引入各自的样式文件
        'antd/lib/style/index.less']
    },
    output: {
      path: outputdir,
      filename: isDev ? 'js/[name].js' : 'js/[name]_[chunkhash:8].js',
      // 使用require.ensure造成的延迟加载的代码文件
      chunkFilename: isDev ? 'js/chunk_[id]_[name].js'
        : 'js/chunk_[name]_[chunkhash:8].js',
      publicPath: webContextRoot
    },
    module: {
      rules: [{
        test: /\.jsx?$/,
        exclude: /(node_modules|bower_components)/,
        use: [{
          // 编译新版本js语法为低版本js语法
          loader: 'babel-loader',
          options: {
            presets: [
              // 编译es2015版本的js
              ['babel-preset-es2015', {
                modules: false
              }], 'babel-preset-stage-2',
              // 编译jsx
              'babel-preset-react'],

            plugins: [// 支持热加载react组件
              isDev ? 'react-hot-loader/babel' : null,
              // 减少重复的编译后的辅助方法
              'babel-plugin-transform-runtime',
              // 按需加载组件的代码和样式
              ['babel-plugin-import', {
                libraryName: 'antd',
                style: true
              }]].filter( hasValue )
          }
        }]
      }, {
        test: /\.css$/,
        use: ['style-loader',
          {
            loader: 'css-loader',
            options: {
              // 第三方组件未以module方式引入css,所以不能在全局开启css module
              modules: false
            }
          },
          { loader: 'postcss-loader', options: { plugins: [WebkitPrefixer] } }]
      }, {
        test: /\.less$/,
        use: ['style-loader',
          {
            loader: 'css-loader',
            options: {
              modules: false
            }
          },
          { loader: 'postcss-loader', options: { plugins: [WebkitPrefixer] } },
          {
            loader: 'less-loader',
            options: {
              modules: false,
              modifyVars: {
                // 替换antd用到的字体文件路径
                "icon-url": JSON.stringify( antd_fonticon )
              }
            }
          }]
      }, {
        test: /\.(jpg|png|gif)$/,
        use: {
          loader: 'url-loader',
          options: {
            // 编码为dataUrl的最大尺寸
            limit: 10000,
            // 输出路径,相对于publicPath
            outputPath: 'assets/',
            name: isDev ? '[name].[ext]' : '[name]_[hash:8].[ext]'
          }
        }

      }, {
        test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/,
        use: {
          loader: 'url-loader',
          options: {
            limit: 10000,
            mimetype: 'application/font-woff',
            outputPath: 'assets/',
            name: isDev ? '[name].[ext]' : '[name]_[hash:8].[ext]'
          }
        }
      }, {
        test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
        use: {
          loader: 'url-loader',
          options: {
            limit: 10000,
            mimetype: 'application/octet-stream',
            outputPath: 'assets/',
            name: isDev ? '[name].[ext]' : '[name]_[hash:8].[ext]'
          }
        }
      }, {
        test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
        use: {
          loader: 'url-loader',
          options: {
            limit: 10000,
            mimetype: 'application/vnd.ms-fontobject',
            outputPath: 'assets/',
            name: isDev ? '[name].[ext]' : '[name]_[hash:8].[ext]'
          }
        }
      }, {
        test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
        use: {
          loader: 'url-loader',
          options: {
            limit: 10000,
            mimetype: 'application/svg+xml',
            outputPath: 'assets/',
            name: isDev ? '[name].[ext]' : '[name]_[hash:8].[ext]'
          }
        }
      }]
    },
    plugins: [
      // momentjs包含大量本地化代码,需筛选
      new webpack.ContextReplacementPlugin( /moment[\/\\]locale$/, /en-ca|zh-cn/ ),
      new webpack.optimize.OccurrenceOrderPlugin( true ),
      // 复制无需编译的文件至输出目录
      new CopyWebpackPlugin( [{
        from: path.resolve( sourcedir, 'assets' ),
        to: 'assets'
      }] ),
      // 修复webpack的chunkhash不以chunk文件实际内容为准的问题
      new WebpackMd5Hash(),
      // 单独打包输出第三方组件,和webpack生成的运行时代码
      new webpack.optimize.CommonsChunkPlugin( {
        name: ['vendor', 'manifest']
      }),
      // 自动填充js、css引用进首页
      new HtmlWebpackPlugin( {
        title: 'wzp react',
        template: path.resolve( sourcedir, 'index.html' ),
        inject: 'body' // Inject all scripts into the body
      }),
      // 设置环境变量
      new webpack.DefinePlugin( {
        process: {
          env: {
            // process.env.NODE_ENV==="production"
            // 应用代码里,可凭此判断是否运行在生产环境
            NODE_ENV: isDev ? JSON.stringify( 'development' )
              : JSON.stringify( 'production' )
          }
        }
      }),
      // print more readable module names on HMR updates
      isDev ? new webpack.NamedModulesPlugin() : null,
      // 先清理输出目录
      isDev ? null : new CleanWebpackPlugin( [outputdir] ),
      // 排除特定库
      isDev ? null : new webpack.IgnorePlugin( /.*/, /react-hot-loader$/ ),
      // 输出报告,查看第三方库的大小
      isDev ? null : new BundleAnalyzerPlugin(
        {
          analyzerMode: 'static',
          reportFilename: 'report.html',
          openAnalyzer: true,
          generateStatsFile: false
        })
    ].filter( hasValue )
  }
};

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JS 按钮点击触发(兼容IE、火狐)
Aug 07 Javascript
jquery easyui使用心得
Jul 07 Javascript
jQuery的animate函数学习记录
Aug 08 Javascript
实现音乐播放器的代码(html5+css3+jquery)
Aug 04 Javascript
项目实践一图片上传之form表单还是base64前端图片压缩(前端图片压缩)
Jul 28 Javascript
Angularjs验证用户输入的字符串是否为日期时间
Jun 01 Javascript
vue2.x 父组件监听子组件事件并传回信息的方法
Jul 17 Javascript
记一次vue去除#问题处理经过小结
Jan 24 Javascript
vue动态配置模板 'component is'代码
Jul 04 Javascript
详解 javascript对象创建模式
Oct 30 Javascript
聊聊JS ES6中的解构
Apr 29 Javascript
Vue中foreach数组与js中遍历数组的写法说明
Jun 05 Vue.js
基于AngularJS实现表单验证功能
Jul 28 #Javascript
AngularJS service之select下拉菜单效果
Jul 28 #Javascript
解决Vue2.0自带浏览器里无法打开的原因(兼容处理)
Jul 28 #Javascript
bootstrap datepicker插件默认英文修改为中文
Jul 28 #Javascript
基于BootStrap multiselect.js实现的下拉框联动效果
Jul 28 #Javascript
基于JS实现移动端左滑删除功能
Jul 28 #Javascript
Vue2.0 多 Tab切换组件的封装实例
Jul 28 #Javascript
You might like
实用函数8
2007/11/08 PHP
PHP的curl实现get,post和cookie(实例介绍)
2013/06/17 PHP
Zend Framework实现多服务器共享SESSION数据的方法
2016/03/22 PHP
Paypal实现循环扣款(订阅)功能
2017/03/23 PHP
php批量删除操作(数据访问)
2017/05/23 PHP
简单实现php上传文件功能
2017/09/21 PHP
javascript读取xml
2006/11/04 Javascript
Firefox和IE浏览器兼容JS脚本写法小结
2008/07/07 Javascript
JavaScript Event学习第七章 事件属性
2010/02/07 Javascript
JS+CSS简单树形菜单实现方法
2015/09/12 Javascript
jQuery实现移动端滑块拖动选择数字效果
2015/12/24 Javascript
jQuery设置聚焦并使光标位置在文字最后的实现方法
2016/08/02 Javascript
JQuery动态添加Select的Option元素实现方法
2016/08/29 Javascript
AngularJS实现路由实例
2017/02/12 Javascript
angular.JS实现网页禁用调试、复制和剪切
2017/03/31 Javascript
JQ图片文件上传之前预览功能的简单实例(分享)
2017/11/12 Javascript
vue-router路由懒加载和权限控制详解
2017/12/13 Javascript
AngularJS使用$http配置对象方式与服务端交互方法
2018/08/13 Javascript
angular1.x ui-route传参的三种写法小结
2018/08/31 Javascript
JS遍历JSON数组及获取JSON数组长度操作示例【测试可用】
2018/12/12 Javascript
javascript跳转与返回和刷新页面的实例代码
2019/11/20 Javascript
AutoJs实现刷宝短视频的思路详解
2020/05/22 Javascript
[02:35]DOTA2英雄基础教程 末日使者
2013/12/04 DOTA
[00:17]DOTA2荣耀之路5:It’s a disastah!
2018/05/28 DOTA
在Linux系统上通过uWSGI配置Nginx+Python环境的教程
2015/12/25 Python
浅谈Python2.6和Python3.0中八进制数字表示的区别
2017/04/28 Python
Python编程产生非均匀随机数的几种方法代码分享
2017/12/13 Python
Python WSGI的深入理解
2018/08/01 Python
python hashlib加密实现代码
2019/10/17 Python
python爬虫用scrapy获取影片的实例分析
2020/11/23 Python
捐书寄语赠言
2014/01/18 职场文书
助学感谢信范文
2015/01/21 职场文书
2015秋季幼儿园开学寄语
2015/03/25 职场文书
2016大学生入党积极分子心得体会
2016/01/06 职场文书
私人贷款担保书该怎么写呢?
2019/07/02 职场文书
Python可视化神器pyecharts绘制水球图
2022/07/07 Python