带有快速把手的 webpack

问题描述

我正在尝试将旧的 express 站点迁移到 webpack,但不想重新设计所有使用 express-handlebars 的布局模板。 webpack 可以使用 express-handlebars 吗?

handlebars-loader 似乎不支持 express-handlebars 的布局概念,所以在这里没有帮助。

解决方法

自定义加载器似乎可以解决问题:

express-handlebars-loader.js

const loaderUtils = require('loader-utils');
const validateOptions = require('schema-utils');
const path = require('path');
const express = require('express');
const exphbs = require('express-handlebars');

module.exports = function (content) {
    const options = loaderUtils.getOptions(this);
    const app = options.app;
    const contextCallback = options.contextCallback;
    const view = path.relative(options.basePath,this.resourcePath);
    const context = contextCallback(this.resourcePath,view);
    
    var loaderAsyncCallback = this.async();
    app.render(view,context,function (err,html) {
        if (err) {
            return loaderAsyncCallback(err);
        }
        
        const slug = 
            '// Module\n'
            + 'var code = ' + JSON.stringify(html) + ';\n'
            + '// Exports\n'
            + 'module.exports = code;'
        
        loaderAsyncCallback(null,slug);
    });
  
};

webpack.config.js

const CopyPlugin = require("copy-webpack-plugin");
const HtmlWebpackPlugin = require('html-webpack-plugin');
const path = require('path');
const fs = require('fs');
const url = require('url');
const express = require('express');
const exphbs = require('express-handlebars');

const app = express();

// Handlebars Setup

/**
 * Instantiate a Handlebars instance with our config (default layout,helpers,etc.)
 */
const handlebasInstance = exphbs.create({
  defaultLayout: 'mainLayout',// Specify helpers which are only registered on this instance.
  helpers
});

app.engine('handlebars',handlebasInstance.engine);
app.set('view engine','handlebars');
app.use('/assets',express.static('assets'));

const basePath = path.resolve(__dirname,'./views');

function generateHtmlPlugins(templateDir) {
  const itemList = fs.readdirSync(templateDir);
  return itemList.flatMap(item => {
    const [ name,extension ] = item.split('.');
    if (extension == 'handlebars') {
        const templatePath = path.resolve(templateDir,item);
        const outputPath = path.resolve(templateDir,name + '.html');
        const outputName = path.relative(basePath,outputPath);
        return new HtmlWebpackPlugin({
          filename: outputName,inject: false,template: templatePath
        })
    } else {
        return [];
    }
  })
}

const siteHtmlPlugins = generateHtmlPlugins(basePath);

function contextCallback(resourcePath,view) {
    var context = {};
    if (view.includes('documentation/')) {
        context.layout = 'documentationLayout';
    }
    return context;
}


module.exports = {
  mode: 'development',resolveLoader: {
    modules: [ 'node_modules',path.resolve(__dirname,'loaders') ]
  },entry: './src/entry-workaround.js',output: {
    filename: 'entry-workaround.js',path: path.resolve(__dirname,'public'),},module: {
    rules: [{
        test: /\.handlebars$/,loader: "express-handlebars-loader",options: {
            app: app,basePath: basePath,contextCallback: contextCallback,}
    }]
  },plugins: []
};

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...