Django/Webpack - 如何使用 webpack 开发服务器提供生成的 webpack 包

myk*_*yke 7 javascript python django webpack webpack-dev-server

Django 的 'static' 标签使用 STATIC_URL 生成 url,结果类似于 '/static/myapp/js/bundle.js' 同时,webpack-dev-server 正在提供来自 url 'localhost:3000' 的包

我的问题是如何让 Django 'static' 模板标签为 js 包生成不同的 url(指向 webpack 开发服务器)。当然,我可以在模板中对其进行硬编码,但这不是一个好的解决方案。

下面是我的项目配置

webpack.config.js

const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const BundleTracker = require('webpack-bundle-tracker')


module.exports = {
    mode: 'development',
    context: path.dirname(path.resolve(__dirname)),
    entry: {
        index: './typescript_src/index.ts',
    },
    output: {
        path: path.resolve('./myproject/assets/myapp/bundles/'),
        filename: "[name]-[hash].js"
    },
    resolve: {
        extensions: ['.ts', '.js' ]
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader']
            },
            {
                test: /\.ts$/,
                use: 'ts-loader',
                exclude: /node_modules/
            }
        ]
    },
    plugins: [
        new CleanWebpackPlugin(),
        new BundleTracker({filename: './myproject/webpack-stats.json'})
    ],
    devServer: {
        port: 3000,
        publicPath: '/myapp/bundles/',
        // hot: true,
        headers: {
            "Access-Control-Allow-Origin": "http://127.0.0.1:8000", /**Django dev server */
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

设置.py

WEBPACK_LOADER = {
    'DEFAULT': {
        'CACHE': not DEBUG,
        'BUNDLE_DIR_NAME': 'myapp/bundles/', # must end with slash
        'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats.json'),
        'POLL_INTERVAL': 0.1,
        'TIMEOUT': None,
        'IGNORE': [r'.+\.hot-update.js', r'.+\.map']
    }
}

STATIC_URL = '/static/'
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'assets'),
)
Run Code Online (Sandbox Code Playgroud)

最初我决定 webpack 也应该在开发过程中提供其他静态文件

webpack.config.js

devServer: {
        port: 3000,
        publicPath: '/myapp/bundles/',
        contentBase: path.resolve('./myproject/assets')
        // hot: true,
        headers: {
            "Access-Control-Allow-Origin": "http://127.0.0.1:8000", /**Django dev server */
        }
Run Code Online (Sandbox Code Playgroud)

设置.py

# in development mode serve from wepack dev server
if DEBUG:
    STATIC_URL = 'http://localhost:3000/'
else:
    STATIC_URL = '/static/'
Run Code Online (Sandbox Code Playgroud)

但后来我意识到我必须提供其他应用程序(admin、tinymce 等)的静态文件,这是 webpack Dev 服务器无法访问的

这里的问题是 django-webpack-loader (/static/myapp/bundles/bundle-name.js) 的 'render_bundle' 标签生成的 url 将导致 Http 404,因为 webpack-dev-server 将生成的包保留在内存而不是磁盘

另外如果我设置

STATIC_URL = localhost:3000
Run Code Online (Sandbox Code Playgroud)

并配置 webpack-dev-server 为我的应用程序的其他静态文件提供服务,其他应用程序的静态文件将不会提供

Eje*_*jez 8

我们来分析一下这个问题:

我们有 2 个服务器,我们希望根据请求的路径将请求路由到其中一个:

"/static/webpackbundles/** ==> webpack dev server

other paths ==> django dev server

这正是代理服务器的工作,它可以通过第三台服务器(haproxy、nginx ...)来实现,但这似乎有点矫枉过正,尤其是如果我们知道它webpack dev server可以用作代理!( https://webpack.js.org/configuration/dev-server/#devserverproxy )

webpack.config.js

const path = require('path');

module.exports = {
  mode: 'development',
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: '/path/to/django_project/django_project/static/webpackbundles',
    publicPath: '/static/webpackbundles/',
  },
  devServer: {
    contentBase: '/path/to/django_project/django_project/static/webpackbundles',
    hot: true,
    proxy: {
      '!/static/webpackbundles/**': {
        target: 'http://localhost:8000', // points to django dev server
        changeOrigin: true,
      },
    },
  },
};
Run Code Online (Sandbox Code Playgroud)

在您的 Django 模板中:

const path = require('path');

module.exports = {
  mode: 'development',
  entry: './src/index.js',
  output: {
    filename: 'main.js',
    path: '/path/to/django_project/django_project/static/webpackbundles',
    publicPath: '/static/webpackbundles/',
  },
  devServer: {
    contentBase: '/path/to/django_project/django_project/static/webpackbundles',
    hot: true,
    proxy: {
      '!/static/webpackbundles/**': {
        target: 'http://localhost:8000', // points to django dev server
        changeOrigin: true,
      },
    },
  },
};
Run Code Online (Sandbox Code Playgroud)

现在使用webpack dev server地址访问您的 django 应用程序/站点:例如:http://localhost:8081

通过这个简单的配置,您将拥有浏览器自动刷新和热模块更换功能。您不需要在 django 中更改任何内容,也不需要 django-webpack-loader