Tomcat部署了war和Webpack代码拆分

时间:2016-08-21 13:39:13

标签: tomcat webpack

我正在使用带有多个入口点和代码拆分的Webpack 2.1.0-beta.20。

分割点使用ES6样式System.import()并根据应用程序的路由触发。这在Webpack开发服务器和使用gradle bootRun启动的Spring Boot嵌入式Tomcat上完美运行。打包到战争并在Tomcat上手动部署时会出现问题。在这种情况下,静态入口点按预期加载。这些是由Webpack注入index.html的。但浏览器显示没有尝试检索“按需加载”块。结果是没有将React应用程序解析为div。

<div> <!-- react-empty: 1 -->

我认为问题在于Tomcat部署使用war的名称作为URL中的应用程序名称。其他运行配置没有。

http://localhost:8080/http://localhost:8080/app-name

找不到任何资源并非失败。我可以在URL上提取第一个块包。这就像Webpack不费力地加载它。我在pathpublicPath上尝试了很多变体。还尝试了__webpack_public_path__。但它似乎不是定位问题。而出于某种原因,Webpack根本没有尝试加载块。

感谢您的任何建议。

webpack.config.js

const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')

const PATHS = {
  app: './app/index.js',
  html: './app/index.html',
  src: path.resolve(__dirname, 'app'),
  dist: path.resolve(__dirname, 'dist'),
  routes: path.resolve(__dirname, 'app/routes')
}

const DEV_PORT = '4000'
const SSL_PORT = '8543'
const HOST = '127.0.0.1'

const HtmlWebpackPluginConfig = new HtmlWebpackPlugin({
  template: PATHS.html,
  filename: 'index.html',
  inject: 'body'
})

module.exports = env => {
  return {
    entry: {
      hmr: getHmrEntry(),
      js: PATHS.app,
      route: PATHS.routes + '/routes.js',
      vendor: [
        'react',
        'react-router',
        'react-dom',
        'babel-polyfill'
      ]
    },

    output: {
      filename: '[name].bundle.js',
      chunkFilename: '[id].bundle.js',
      path: PATHS.dist,
      publicPath: getPublicPath()
    },

    context: __dirname,

    resolve: {
      modules: [path.resolve(__dirname, '.'), 'node_modules']
    },

    devtool: env.prod ? 'eval' : 'inline-source-map',

    bail: env.prod,

    externals: {
      'cheerio': 'window',
      'react/lib/ExecutionEnvironment': true,
      'react/lib/ReactContext': true
    },

    module: {
      loaders: [
        {
          test: /(\.js|\.jsx)$/,
          exclude: /node_modules/,
          loaders: ['react-hot', 'babel?presets[]=react,presets[]=es2015,presets[]=stage-2', 'eslint']
        },
        {
          test: /\.css$/,
          loader: ExtractTextPlugin.extract({
            fallbackLoader: 'style-loader',
            loader: ['css']
          })
        }
      ]
    },

    plugins: [
      HtmlWebpackPluginConfig,

      new webpack.optimize.CommonsChunkPlugin({
        name: 'vendor',
        minChunks: Infinity,
        filename: 'vendor.bundle.js'
      }),

      new ExtractTextPlugin({
        filename: '[name].[id].style.css',
        allChunks: false
      })
    ],

    devServer: {
      contentBase: PATHS.dist,
      port: DEV_PORT,
      historyApiFallback: true
    }
  }

  function getPublicPath () {
    // var prodPath = 'https://' + HOST + ':' + SSL_PORT + '/react-app/'
    var prodPath = '/react-app/'
    // var devPath = 'http://' + HOST + ':' + PORT + '/dist/'
    var devPath = '/dist/'
    var publicPath

    if (env.prod) {
      publicPath = prodPath
    } else {
      publicPath = devPath
    }
    return publicPath
  }

  function getHmrEntry () {
    var hmr = []
    if (!env.prod) {
      hmr = [
        'webpack-dev-server/client?http://' + HOST + ':' + DEV_PORT,
        'webpack/hot/only-dev-server'
      ]
    }
    return hmr
  }
}

index.js

import 'babel-polyfill'
import React from 'react'
import { render } from 'react-dom'
import { Router, browserHistory } from 'react-router/es6'
import rootRoute from './routes/routes'
import '../style/common.css'
// __webpack_public_path__ = window.resourceBaseUrl + '/react-app/'

render(
  <Router history={browserHistory} routes={rootRoute} />,
  document.getElementById('root')
)

routes.js

import App from '../containers/App'

function errorLoading (err) {
  console.error('Dynamic page loading failed', err)
}

function loadRoute (cb) {
  return (module) => cb(null, module.default)
}

export default {
  component: App,
  childRoutes: [
    {
      path: '/',
      getComponent (location, cb) {
        System.import('./Home')
          .then(loadRoute(cb))
          .catch(errorLoading)
      }
    },
    {
      path: 'about',
      getComponent (location, cb) {
        System.import('./About')
          .then(loadRoute(cb))
          .catch(errorLoading)
      }
    },
    {
      path: 'feature',
      getComponent (location, cb) {
        System.import('./Feature')
          .then(loadRoute(cb))
          .catch(errorLoading)
      }
    }
  ]
}

2 个答案:

答案 0 :(得分:0)

修复是在创建basename实例时添加browserHistory而不是仅导入它。上面index.js更改为:

import 'babel-polyfill'
import React from 'react'
import { render } from 'react-dom'
import { Router } from 'react-router/es6'
import { createHistory, useBasename } from 'history'
import rootRoute from './routes/routes'
import '../style/common.css'

const browserHistory = useBasename(createHistory)({
  basename: '/react-app'
})

render(
  <Router history={browserHistory} routes={rootRoute} />,
  document.getElementById('root')
)

感谢参与讨论的人们 - https://github.com/reactjs/react-router/issues/353

答案 1 :(得分:0)

已弃用上述history。这是一个更新的版本:

import 'babel-polyfill'
import { render } from 'react-dom'
import React from 'react'
import { Router, useRouterHistory } from 'react-router/es6'
import { createHistory } from 'history'
import rootRoute from './routes/routes'
import '../style/common.css'

const browserHistory = useRouterHistory(createHistory)({ basename: '/react-app' })

render(
  <Router history={browserHistory} routes={rootRoute} />,
  document.getElementById('root')
)