Hi!
Any plans for adding handlebars, jade or markdown out of the box?
If not can anyone tell how to make work markdown for example?
No plans, but you can use mix.webpackConfig to add any custom configuration.
@vladimir-yuldashev this is how I use Handlebars in my project, simple extend the webpackConfig with the handlebars-loader plugin.
mix.webpackConfig({
module: {
rules: [
{
test: /\.handlebars?$/,
loader: 'handlebars-loader'
}
]
}
});
You should be able to do something similar with Markdown.
@puredazzle Great, thanks!
To add another solution I'm using for handlebars.js:
let mix = require('laravel-mix');
let Handlebars = require("handlebars");
let path = require('path');
let fs = require('fs');
mix.extend('hbs', function(webpackConfig, ...args) {
fs.writeFileSync(args[1], 'Handlebars.templates = Handlebars.templates || {};\n\n');
Object.keys(args[0]).map(function(name, index) {
let relPath = args[0][name];
let template = fs.readFileSync(path.resolve(relPath), 'utf8');
let compiled = Handlebars.precompile(template);
fs.appendFileSync(args[1], 'Handlebars.templates[\''+name+'\'] = Handlebars.template('+compiled+');\n\n');
});
});
mix.hbs({
'array.key_name': 'path/to/handlebars/template.hbs',
}, 'public/js/templates.hbs.js');
and in your JavaScript you can use it after this Handlebars.templates['array.key_name'](data). I bet that this could be improved - but it's working. :)
This is what worked for me, I needed one template compiled with different data to two different files:
let mix = require('laravel-mix')
const Task = require('laravel-mix/src/tasks/Task')
const FileCollection = require('laravel-mix/src/FileCollection')
const Handlebars = require('handlebars')
const fs = require('fs')
const spanish = require('./src/lang/spanish')
const english = require('./src/lang/english')
class CompileHandlebarsTask extends Task {
run() {
this.files = new FileCollection(this.data.template_path);
this.compile()
}
onChange(updatedFile) {
this.compile()
}
compile () {
let template = Handlebars.compile(fs.readFileSync(this.data.template_path).toString())
fs.writeFileSync(this.data.compiled_path, template(this.data.data))
console.log(`Handlebars template ${this.data.compiled_path} compiled`)
}
}
class Hbs {
name () {
return 'hbs';
}
register(template_path, compiled_path, data) {
console.log('mix.hbs() was called ', template_path, '->', compiled_path);
Mix.addTask(new CompileHandlebarsTask({ template_path, compiled_path, data }))
}
}
mix.extend('hbs', new Hbs())
mix
.hbs('src/home.hbs', 'dist/index.html', spanish)
.hbs('src/home.hbs', 'dist/english.html', english)
.copyDirectory('src/img', 'dist/img')
.js('src/js/script.js', 'dist/js')
.sass('src/css/styles.scss', 'dist/css')
.sourceMaps();
I use laravel-mix as a stand-alone project and here I need handlebars with layout. So I built a small package for this, so handlebars can be easily integrated into Laravel Mix.
@ramsesmoreno Many thanks for your code snippet helped me a lot in developing the package.
@4ern thanks for your extension!
Does it work for you with browserSync? I can't get page automatically reloading then .hbs files is updated
Unfortunately not with mix.browserSync. Unfortunately, I don't know why. But it works if you load it directly over webpack.
// example
mix.webpackConfig(() => {
return {
plugins: [
new BrowserSyncPlugin({
host: 'localhost',
port: 3003,
watch: true,
server: { baseDir: ['dist'] }
})
]
};
});
@ramsesmoreno Thank you so much for your snippet.
@4ern Thanks for your package as well. Unfortunately I can't get it working properly and have filed an issue under your repo with all the details.
Below is a modified version of @ramsesmoreno 's code to include support for Handlebars Layouts. This works in the same way as @4ern 's package. This is no where near perfect, but for now it works for me.
Files with _ prefixed get registered as partials. The name of the partial registered has the _ prefix stripped.
Example: _layout.hbs will get registered as layout
const mix = require('laravel-mix');
const Task = require('laravel-mix/src/tasks/Task');
const FileCollection = require('laravel-mix/src/FileCollection');
const Handlebars = require('handlebars');
const HandlebarsLayouts = require('handlebars-layouts');
const fs = require('fs');
Handlebars.registerHelper(HandlebarsLayouts(Handlebars));
class CompileHandlebarsTask extends Task {
run() {
this.files = new FileCollection(this.data.template_path);
this.compile()
}
onChange(updatedFile) {
this.compile()
}
compile () {
let template = Handlebars.compile(fs.readFileSync(this.data.template_path).toString())
fs.writeFileSync(this.data.compiled_path, template(this.data.data))
console.log(`Handlebars template ${this.data.compiled_path} compiled`)
}
}
class Hbs {
constructor(tplPath) {
console.log('mix extending hbs - register partials', tplPath);
fs.readdirSync(tplPath).forEach(file => {
if (file.charAt(0) == '_') {
let partialName = file.substring(1).replace('.hbs', '');
let partialPath = tplPath + file;
console.log('handlebars registering partial', partialName, partialPath);
Handlebars.registerPartial(
file.substring(1).replace('.hbs', ''),
fs.readFileSync(tplPath + file, 'utf8')
);
}
});
}
name () {
return 'hbs';
}
register(template_path, compiled_path, data) {
console.log('mix.hbs() was called ', template_path, '->', compiled_path);
Mix.addTask(new CompileHandlebarsTask({
template_path,
compiled_path,
data
}));
}
}
mix.extend('hbs', new Hbs('src/hbs/'));
Most helpful comment
@vladimir-yuldashev this is how I use Handlebars in my project, simple extend the webpackConfig with the handlebars-loader plugin.
You should be able to do something similar with Markdown.