迁移到Webpack 2以进行React应用程序

时间:2016-08-11 03:37:45

标签: webpack react-router

我已经看到了webpack 2的复杂设置及其带来的好处。让我想升级到版本2的原因之一是Webpack 2不会导入除此之外的其他

import { Router, Route, browserHistory, IndexRoute } from 'react-router'

所以我认为这会帮助我减少包react-router的文件大小。另一件需要考虑的事情是因为互联网上显示的很多例子都是他们实现Webpack 2.我寻求帮助将webpack.config.js升级到此版本

require('dotenv').load();
var fs = require('fs');
var autoprefixer = require('autoprefixer');
var path = require('path');
var webpack = require('webpack');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var HtmlWebpackPlugin = require('html-webpack-plugin');

module.exports = {
    //debug: true,
    devtool: 'cheap-source-map',
    entry: [
        'webpack-dev-server/client?http://localhost:3000', 
        'webpack/hot/only-dev-server', 
        './app/App.js'
    ],
    output: {
        // pathinfo: true,
        path: path.resolve(__dirname, 'public'),
        filename: '[name].js',
        chunkFilename: '[id].chunk.js',
        publicPath: 'http://localhost:3000/'
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: './index_template.ejs',
            inject: 'body',
            minify: {
              removeComments: true,
              collapseWhitespace: true,
              removeRedundantAttributes: true,
              useShortDoctype: true,
              removeEmptyAttributes: true,
              removeStyleLinkTypeAttributes: true,
              keepClosingSlash: true,
              minifyJS: true,
              minifyCSS: true,
              minifyURLs: true
            }
        }),
        new webpack.HotModuleReplacementPlugin(),
        // new webpack.optimize.CommonsChunkPlugin('shared.js'),
        // new webpack.optimize.CommonsChunkPlugin('vendor', './public/js/vendor.js')
        new webpack.DefinePlugin({
          'process.env.ES_URL': JSON.stringify(process.env.ES_URL)
        })
    ],
    module: {
        loaders: [
            {
                test: /\.js$/,
                exclude: /(node_modules|bower_components)/,
                loaders: ['react-hot', 'babel']
            },
            {
                test: /\.styl$/,
                exclude: /(node_modules|bower_components)/,
                loader: 'style!css?sourceMap&modules&importLoaders=1&localIdentName=[name]__[local]__[hash:base64:5]!postcss!stylus-loader'
            },
            {
                test: /\.(png|jpg)$/,
                exclude: /(node_modules|bower_components)/,
                loader: 'url-loader?name=images/[name].[ext]&limit=8192'
            },
            {
                test: /\.(ttf|otf|eot)$/,
                exclude: /(node_modules|bower_components)/,
                loader: 'url-loader?name=fonts/[name].[ext]&limit=8192'
            },
            {
                test: /\.css$/,
                loader:  'style!css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]'
            },
            {
                test: /\.scss$/,
                loader:  'style!css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!postcss!sass?resolve url'
            },
            {
                test: /\.json$/,
                loader: 'json-loader'
            }, 
            {
                test: /\.js$/,
                include: path.resolve('node_modules/mapbox-gl-shaders/index.js'),
                loader: 'transform/cacheable?brfs'
            },
            {
                test: /aws-sdk/, 
                loaders: ["transform?brfs"] 
            },
        ],
        postLoaders: [{
            include: /node_modules\/mapbox-gl-shaders/,
            loader: 'transform',
            query: 'brfs'
        }]
    },
    resolve: {
        root: path.join(__dirname, '..', 'app'),
        alias: {
            'react': path.join(__dirname, 'node_modules', 'react'),
            'react-router': path.join(__dirname, 'node_modules', 'react-router'),
            'mapbox-gl': path.resolve('./node_modules/mapbox-gl/dist/mapbox-gl.js'),
            'webworkify': 'webworkify-webpack'
        },
        extensions: ['', '.js', '.jsx', '.json', '.css', '.styl', '.png', '.jpg', '.jpeg', '.gif']
    },
    postcss: function () {
        return [autoprefixer];
    }
};

这里的路由器设置让我无法进行代码分割

<Route path="/" component={Main}>
    <IndexRoute getComponent={(nextState, cb) => {require.ensure([], require => {cb(null, Home)})}}/>
    <Route path="s" getComponent={(nextState, cb) => {require.ensure([], require => {cb(null, Search)})}} /* onEnter={requireAuth} */ />
    <Route path="login" getComponent={(nextState, cb) => {require.ensure([], require => {cb(null, LoginFrom)})}}/>
    <Route path="signup" getComponent={(nextState, cb) => {require.ensure([], require => {cb(null, SignUpForm)})}}/>
</Route>

1 个答案:

答案 0 :(得分:2)

以下是我在项目中的表现,我的配置与您的配置有些相似,我认为可以帮助您

<强> webpack.config.babel.js

import webpack from 'webpack'
import CopyWebpackPlugin from 'copy-webpack-plugin'
import HtmlWebpackPlugin from 'html-webpack-plugin'
import OpenBrowserPlugin from 'open-browser-webpack-plugin'
import CleanWebpackPlugin from 'clean-webpack-plugin'
import ExtractTextPlugin from 'extract-text-webpack-plugin'
import path from 'path'
import {sitePort, siteUrl} from './app/config'
import dir from 'webpack-directory-scan'
import ProgressBarPlugin from 'progress-bar-webpack-plugin'



let myModules = dir.get('./','dist')

let port = sitePort
let env = process.env.NODE_ENV

let sourceMap = 'source-map'
let buildFolder = 'dist/development/'
let publicPath = siteUrl+buildFolder



if (env === 'production') {
    sourceMap = ''
    buildFolder = 'dist/production/'
    publicPath = siteUrl
}

export default {
    devtool: sourceMap,
    entry: './app/index.js',
    output: {
        filename: 'bundle.js',
        path: path.join(__dirname, buildFolder),
        publicPath: publicPath
    },
    devServer: {
        historyApiFallback: true,
        contentBase: buildFolder,
        noInfo: true,
        port: port
    },
    module: {
        rules: [
            {
                test: /\.(js|jsx)$/,
                exclude: /node_modules/,
                use: 'babel-loader'
            },
            {
                test: /\.(woff|woff2|eot|ttf)$/i,
                use: 'file-loader?name=/font/[name].[ext]'
            },
            {
                test: /\.(jpe?g|gif|png|svg)$/i,
                use: 'file-loader?name=/image/[name].[ext]'
            },
            {
                test: /vendor\/.+\.(js|jsx)$/,
                use: 'imports-loader?jQuery=jquery,$=jquery,this=>window'
            },
            {
                test: /\.(css|scss)$/,
                loader: ExtractTextPlugin.extract({
                    loader: [
                        { loader: 'css-loader?sourceMap&modules&importLoaders=1&localIdentName=[name]___[hash:base64:5]'},
                        { loader: 'resolve-url-loader'},
                        { loader: 'sass-loader?sourceMap'},
                        { loader: 'postcss-loader?sourceMap'},
                    ]
                })
            }
        ]

    },
    resolve: {
        modules: [...myModules, 'node_modules']
    },
    plugins: [
        new webpack.EnvironmentPlugin(['NODE_ENV']),
        // if env==='devserver' no folder will be deleted
        new CleanWebpackPlugin([buildFolder],{dry: env==='devserver',verbose: false}),
        new CopyWebpackPlugin([
            {from: 'image', to: 'image'}
        ]),
        new ExtractTextPlugin({
            filename:'bundle.css',
            disable:false,
            allChunks: true
        }),
        new HtmlWebpackPlugin({
            template: 'app/index.html',
            filename: 'index.html',
            inject: 'body',
            hash: true
        }),
        new OpenBrowserPlugin({ 
            url: 'http://localhost:'+port, 
            browser: 'google chrome'
        }),
        new ProgressBarPlugin(),

    ]
}

<强> .babelrc

{
    "presets": [
        "es2015",
        "react",
        "stage-0"
    ],
    "env": {
        "production": {
            "plugins": ["transform-remove-console"]
        }
    },
    "plugins": [
        "transform-decorators-legacy",
        "react-html-attrs",
        "transform-flow-strip-types",
        [
            "react-css-modules",
            {
                "generateScopedName": "[name]___[hash:base64:5]"
            }
        ],
        [
            "react-intl",
            {
                "messagesDir": "./translation/defaultMessage",
                "enforceDescriptions": false
            }
        ]
    ]
}

<强> postcss.config.js

module.exports = {
    plugins: {
        'postcss-import': {},
        'postcss-cssnext': {
            browsers: ['last 2 versions', '> 5%'],
        },
    },
}

<强>的package.json

"dependencies": {
  "axios": "^0.15.3",
  "axios-mock-adapter": "^1.7.1",
  "babel-plugin-react-css-modules": "^1.2.0",
  "classnames": "^2.2.5",
  "firebase": "^3.6.4",
  "intl": "^1.2.5",
  "jquery": "^3.1.1",
  "latinize": "^0.4.0",
  "moment": "^2.17.1",
  "pikaday": "^1.5.1",
  "ramda": "^0.23.0",
  "react": "^15.4.1",
  "react-autosuggest": "^7.0.2",
  "react-document-title": "^2.0.2",
  "react-dom": "^15.4.1",
  "react-hotkeys": "^0.9.0",
  "react-intl": "^2.2.2",
  "react-intl-redux": "^0.2.0",
  "react-modal": "^1.6.4",
  "react-onclickoutside": "^5.8.3",
  "react-redux": "^5.0.1",
  "react-router": "^3.0.0",
  "react-router-redux": "^4.0.7",
  "react-select": "^1.0.0-rc.2",
  "react-textarea-autosize": "^4.0.5",
  "react-tooltip": "^3.2.2",
  "redux": "^3.6.0",
  "redux-observable": "^0.12.2",
  "redux-thunk": "^2.1.0",
  "store": "^1.3.20",
  "valid-url": "^1.0.9",
  "validator": "^6.2.0",
  "youtube-url": "^0.5.0"
},
"devDependencies": {
  "babel-cli": "^6.18.0",
  "babel-core": "^6.21.0",
  "babel-eslint": "latest",
  "babel-loader": "^6.2.10",
  "babel-plugin-react-html-attrs": "latest",
  "babel-plugin-react-intl": "^2.3.0",
  "babel-plugin-transform-decorators-legacy": "^1.3.4",
  "babel-plugin-transform-remove-console": "^6.8.0",
  "babel-preset-es2015": "^6.18.0",
  "babel-preset-react": "^6.16.0",
  "babel-preset-stage-0": "*",
  "babel-register": "^6.18.0",
  "chai": "^3.5.0",
  "clean-webpack-plugin": "^0.1.14",
  "cli": "^1.0.1",
  "copy-webpack-plugin": "^4.0.1",
  "css-loader": "^0.26.1",
  "enzyme": "^2.7.0",
  "es6-promise": "^4.0.5",
  "eslint": "^3.12.2",
  "eslint-plugin-flowtype": "^2.29.2",
  "eslint-plugin-mocha": "^4.8.0",
  "eslint-plugin-react": "^6.8.0",
  "extract-text-webpack-plugin": "2.0.0-beta.4",
  "file-loader": "^0.9.0",
  "flow-bin": "^0.37.4",
  "html-webpack-plugin": "^2.24.1",
  "imports-loader": "^0.7.0",
  "isomorphic-fetch": "^2.2.1",
  "mocha": "^3.2.0",
  "mocha-loader": "^1.0.0",
  "mocha-webpack": "^0.7.0",
  "node-sass": "^4.1.1",
  "nodemon": "^1.11.0",
  "null-loader": "^0.1.1",
  "open-browser-webpack-plugin": "0.0.3",
  "postcss-cssnext": "^2.9.0",
  "postcss-import": "^9.0.0",
  "postcss-loader": "^1.2.1",
  "precss": "^1.4.0",
  "progress-bar-webpack-plugin": "^1.9.1",
  "react-addons-test-utils": "^15.4.1",
  "react-css-modules": "^4.1.0",
  "react-intl-translations-manager": "^4.0.0",
  "redux-logger": "^2.7.4",
  "redux-mock-store": "^1.2.1",
  "resolve-url-loader": "^1.6.1",
  "sass-loader": "^4.1.1",
  "sinon": "^1.17.6",
  "style-loader": "^0.13.1",
  "stylelint-webpack-plugin": "^0.4.2",
  "url-loader": "^0.5.7",
  "webpack": "2.1.0-beta.25",
  "webpack-dev-server": "2.1.0-beta.10",
  "webpack-directory-scan": "^1.1.226",
  "webpack-node-externals": "^1.5.4"
}