【问题标题】:fixing relative paths with css-loader and react-router使用 css-loader 和 react-router 修复相对路径
【发布时间】:2016-08-04 22:19:18
【问题描述】:

我不知道如何配置 webpack 以生成具有有效 url 的 css,无论当前的应用程序 url 是什么。这是我的项目结构:

/theme
    /assets
        /css
        /fonts
        /images
        /js
/dist
    bundle.js
    index.html
/node_modules
/src
/test
package.json
webpack.config.js

/theme 目录是一个引导主题。 css 中的 url 是相对的。例如:

/* /theme/assets/css/ace-fonts.css */

@font-face {
  font-family: 'Open Sans';
  font-style: normal;
  font-weight: 300;
  src: local('Open Sans Light'), local('OpenSans-Light'), url(../fonts/OpenSans-300.woff) format('woff');
}
@font-face {
  font-family: 'Open Sans';
  font-style: normal;
  font-weight: 400;
  src: local('Open Sans'), local('OpenSans'), url(../fonts/OpenSans-400.woff) format('woff');
}

当我访问我的应用程序时,它的根 url(http://localhost:8080/) 或带有单个段的 url (http://localhost:8080/about) 一切正常。这些相对 url 被解析为基本 url。但是,如果我在 2+ 段 url(http://localhost:8080/some/thing) 上刷新浏览器,浏览器最终会请求以下 url:

http://localhost:8080/some/db812d8a70a4e88e888744c1c9a27e89.woff

React 路由器最终会为 url 构建正确的标记,但样式表中的 url 是相对的,因此会中断。我是 webpack 的新手,不知道如何解决这个问题。

这是我的 webpack 配置:

var path = require('path');
var webpack = require('webpack');

var prodPlugins = [
  new webpack.optimize.DedupePlugin(),
  new webpack.optimize.OccurrenceOrderPlugin(),
  new webpack.optimize.UglifyJsPlugin()
];

var defaultPlugins = [
  new webpack.ProvidePlugin({
    $: "jquery", 
    jQuery: "jquery",
    "window.$": "jquery",
    "window.jQuery": "jquery"
  }),
  new webpack.HotModuleReplacementPlugin()
];

module.exports = {
  entry: [
    'webpack-dev-server/client?http://localhost:8080',
    'webpack/hot/only-dev-server',
    './src/index.js'
  ],
  output: { 
    path: 'dist',
    filename: 'bundle.js'
  },
  devServer: {
    contentBase: './dist',
    hot: true
  },
  resolve: {
    root: path.resolve('./')
  },
  module: {
    loaders: [
      {
        test: /\.jsx?$/,
        exclude: /node_modules/,
        loader: 'react-hot!babel'
      },
      { 
        test: /\.css$/, 
        loader: 'style!css!resolve-url'
      },
      { test: /\.less$/, loader: "style!css!less"},
      { test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: "file" },
      { test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "url-loader?limit=10000&mimetype=application/font-woff" },
      { test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=application/octet-stream" },
      { test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=image/svg+xml" },
      { test: /\.(png|jpg)$/, loader: 'url?limit=8192' }
    ]
  },
  resolveUrlLoader: {
    absolute: true
  },
    plugins: process.env.NODE_ENV === 'production' ? prodPlugins.concat(defaultPlugins) : defaultPlugins,
};

任何帮助将不胜感激。

【问题讨论】:

  • 尝试将/publicPath 添加到您的output 对象:*.com/questions/28846814/…
  • 谢谢!我有一些事情要处理extract-text-webpack-plugin,但/publicPath 是缺失的部分。
  • 太棒了,这个该死的领域已经把我绊倒了很多次!

标签: reactjs webpack react-router css-loader


【解决方案1】:

我最终使用extract-text-webpack-plugin 将我的css 文件放在根路径下。这解决了我在我的 css 文件中的相对路径问题,但后来我注意到我的组件中引用的图像路径不正确,所以根据@lux 的建议,我将我的publicPath 设置为/。这是我更新的 webpack.config.js

var path = require('path');
var webpack = require('webpack');
var ExtractTextPlugin = require('extract-text-webpack-plugin');

var prodPlugins = [
  new webpack.optimize.DedupePlugin(),
  new webpack.optimize.OccurrenceOrderPlugin(),
  new webpack.optimize.UglifyJsPlugin()
];

var defaultPlugins = [
  new webpack.ProvidePlugin({
    $: "jquery", 
    jQuery: "jquery",
    "window.$": "jquery",
    "window.jQuery": "jquery"
  }),
  new webpack.HotModuleReplacementPlugin(),
  new ExtractTextPlugin('styles.css')
];

module.exports = {
  entry: [
    'webpack-dev-server/client?http://localhost:8080',
    'webpack/hot/only-dev-server',
    './src/index.js'
  ],
  output: { 
    path: 'dist',
    publicPath: '/',
    filename: 'bundle.js'
  },
  devServer: {
    contentBase: './dist',
    hot: true
  },
  resolve: {
    root: path.resolve('./')
  },
  module: {
    loaders: [
      {
        test: /\.jsx?$/,
        exclude: /node_modules/,
        loader: 'react-hot!babel'
      },
      {
        test: /\.css$/, 
        loader: ExtractTextPlugin.extract('style-loader', 'css-loader')
      },
      { test: /\.less$/, loader: "style!css!less"},
      { test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, loader: "file" },
      { test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/, loader: "url?limit=10000&mimetype=application/font-woff" },
      { test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=application/octet-stream" },
      { test: /\.svg(\?v=\d+\.\d+\.\d+)?$/, loader: "url?limit=10000&mimetype=image/svg+xml" },
      { test: /\.(png|jpg)$/, loader: 'url?limit=8192' }
    ]
  },
  resolveUrlLoader: {
    absolute: true
  },
  plugins: process.env.NODE_ENV === 'production' ? prodPlugins.concat(defaultPlugins) : defaultPlugins,
};

因为我将 css 提取到 styles.css 文件,所以我必须更新我的 dist/index.html 文件。

<!doctype html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>My App</title>
    <link rel="stylesheet" type="text/css" href="/styles.css">
  </head>
  <body class="no-skin">
    <div id="app"></div>
    <script src="/bundle.js"></script>
  </body>
</html>

【讨论】: