使用 webpack 提供 public 个静态文件

serve public static files with webpack

我很难按照自己的意愿配置 webpack。 我 运行 我的开发服务器在 localhost:8080 上,想通过 localhost:8080/static/js/bundle.js[=31 为我的应用程序提供服务=] 这就是我在下面附加的 webpack.config.js 文件中得到的。在我的文件结构中,我还附加了我还想将位于 dist/static 中的其他文件作为静态文件提供,因此 localhost:8080/[=例如,38=].css 将提供此 dist/static/css/style.css 文件。

这可能是我在配置文件中做错了什么,我对 webpack 不是很熟悉,所以我不知道我问这个问题是否能让你理解。

我的目录树是:

client
  -- /dist
    -- /templates
      -- /admin
        -- index.html
    -- /static
      -- /css
        -- style.css
      -- /js
  -- /node_modules
  -- /src
  -- /test
  -- package.json
  -- webpack.config.json

webpack.config.js

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

var plugins = [
    new webpack.ProvidePlugin({
        'fetch': 'imports?this=>global!exports?global.fetch!whatwg-fetch'
    }),
    new ExtractTextPlugin('app.css', {
        allChunks: true
    }),
    new webpack.DefinePlugin({
        'process.env.NODE_ENV': JSON.stringify(process.env.NODE_ENV || 'development')
    })
];

var cssLoader = {};

if(process.env.NODE_ENV == 'production'){
    plugins.push(
        new webpack.optimize.UglifyJsPlugin()
    );

    cssLoader = {
        test: /\.css$/,
        loader: ExtractTextPlugin.extract('style', 'css?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]')
    };

} else {

    cssLoader = {
        test: /\.css$/,
        loaders: [
            'style?sourceMap',
            'css?modules&importLoaders=1&localIdentName=[path]___[name]__[local]___[hash:base64:5]'
        ]
    }

}

module.exports = {
    entry: [
        'react-hot-loader/patch',
        'webpack-dev-server/client?http://localhost:8080',
        'webpack/hot/only-dev-server',
        './src/index.js'
    ],
    module: {
        loaders: [
            {
                test: /\.jsx?$/,
                exclude: /node_modules/,
                loaders: ['babel']
            },
            cssLoader
        ]
    },
    resolve: {
        extensions: ['', '.js', '.jsx']
    },
    output: {
        path: __dirname + '/dist/static',
        publicPath: '/static/js',
        filename: 'bundle.js'
    },
    devServer: {
        contentBase: './dist/templates/admin',
        hot: true,
        historyApiFallback: true
    },
    plugins: plugins
};

dist/templates/admin/index.html

<!DOCTYPE html>
<html>
<head>
    <title>My App</title>
    <link href="static/css/style.css" type="text/css" rel="stylesheet" />
</head>
<body>
<div id="app"></div>
<script src="static/js/bundle.js"></script>
</body>
</html>

谢谢大家:)

您在端口 8080 上提供应用程序。在您的 webpack 配置中,我看到您设置了内容库 dist/template/Admin,但我在任何地方都看不到该文件夹​​。当您设置内容库时,它将从该文件夹提供 Admin.html,如果您在该文件中声明了依赖项,它将从您那里加载。 You can take a look at this seed 了解更多。

很明显,在某种程度上,webpack-dev-server 不应该用作后端来加载静态文件,例如 CSS 或其他静态 JS,当您 运行将另一台服务器放在一边。当您将 contentBase 键设置为特定目录时,文档说您必须在那里创建一个 index.html 文件,您可以基于此目录提供文件。

如果你想从其他目录提供静态文件并且你有另一个服务器在做它运行与 webpack-dev-server 并行,请注意 this section of the documentation

我所做的是 运行 localhost:8080 上的 webpack-dev-server 和 localhost:3000 上的后端服务器] 并且我的后端服务器在 localhost:3000/ 上从它的根路径提供 admin/index.html ,并在 html 文件中将 bundle.js 的导入更改为绝对路径 <script src="http://localhost:8080/static/js/bundle.js"></script>.

热重载现在工作正常,现在我还可以从我的 webpack 配置文件中删除 contentBase 参数。

重要提示:

  1. 现在 运行 我们想要的 webpack 并使热重载真正起作用,只需在 运行 时添加 --inline,类似于:webpack-dev-server --progress --colors --hot --config ./webpack.config.js --inline
  2. 你也可以使用iframe模式,不过我没有深入研究。
  3. 仍然遇到一个问题,即在构建项目时我必须手动删除绝对路径,这很烦人。现在正在寻找如何自动解决它。

问题

问题的根源是 WebpackDevServer 仅从一个文件夹 提供服务。您应该从中提供服务的文件夹是包含 index.html 的文件夹,这是您正确执行的操作。

到目前为止,您只 ./dist/templates/admin 的内容提供服务,因此当您在其他目录中查找文件时,您会收到 404。这里唯一的例外是你的包,因为你正在设置一个publicPath,它使对路由/static/js的任何请求都被重定向到你的输出,它存储在内存中。

您需要 WebpackDevServer 才能从其他文件夹提供服务。在您的具体情况下,当您请求路径 /static/css.

时,您还需要从 ./dist/static/css 提供服务

解决方案

您需要在 WebpackDevServer 中设置一些中间件。您可以按照 documentation of devServer.setup. To do so, I suggest you use express.static 中的说明进行操作,因为您可能已经在使用 Express。

您需要要求快递:

const express = require('express')

然后,修改devServer如下:

devServer: {
  contentBase: './dist/templates/admin',
  hot: true,
  historyApiFallback: true,
  setup (app) {
    app.use('/static/css/',
      express.static(path.join(__dirname, 'dist', 'static', 'css')));
    /* Using this commented code will break the HMR, see edit
    app.use('/static/js/',
      express.static(path.join(__dirname, 'dist', 'static', 'js')));
    */
    
    // in general
    app.use('/public/route/',
      express.static('/your/local/path'));
  }
}

这样你的开发和构建路径保持不变,WebpackDevServer 在你需要的路径上提供你需要的静态文件。

编辑

我刚刚发现上面的代码破坏了模块热替换。原因是设置中的中间件正在处理 /static/js/,因此包是从文件系统而不是内存提供的。

要继续从内存中获取包,请在 output 属性 中定义一个 publicPath,并且不要从 devServer.setup 中的自定义中间件处理它。

module.exports = {
  
  output: {
    path: ...,
    filename: ...,
    publicPath: '/static/js/'
  },
  
  devServer: {
    contentBase: './dist/templates/admin',
    hot: true,
    historyApiFallback: true,
    setup (app) {
      app.use('/static/css/',
        express.static(path.join(__dirname, 'dist', 'static', 'css')));
    }
  },

  // other properties: entry, module, etc.
}