Search code examples
laravelwebpacklaravel-mixmonaco-editor

Laravel Mix and Monaco Editor


Let's start by saying I'm not very proficient with Webpack, so, it might be a trivial question.

I'm trying to use Monaco in a Laravel project through the monaco-editor-webpack-plugin. Since the plugin needs modifications to webpack.config.js and Laravel uses webpack.mix.js, by fiddling around I managed to come up with the following configuration:

/* eslint-disable import/no-extraneous-dependencies */

const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');

const mix = require('laravel-mix');

/*
 |--------------------------------------------------------------------------
 | Mix Asset Management
 |--------------------------------------------------------------------------
 |
 | Mix provides a clean, fluent API for defining some Webpack build steps
 | for your Laravel applications. By default, we are compiling the CSS
 | file for the application as well as bundling up all the JS files.
 |
 */

mix.js('resources/js/app.js', 'public/js')
    .sass('resources/scss/app.scss', 'public/css')
    .webpackConfig({
        plugins: [
            new MonacoWebpackPlugin({
                languages: ['css', 'html', 'javascript', 'json', 'scss', 'typescript'],
            }),
        ],
    });

Now, everything works fine, files get compiled and the editor works as expected. The Issue I'm having is that the editor's compiled files are being generated in the /public directory. E.g: /public/editor.worker.js, /public/0.js, etc.

I would really like to avoid this and have those files compiled in /public/js/vendor/monaco instead. I tried to change the output config to /public/js/vendor/monaco but it compiles everything (css, fonts, etc) into that directory.

Is there a way to say "Hey, I want those Monaco files here while leaving everything else as is?".


Solution

  • There is a built-in laravel-mix function copy to help. What you can do is, leave the output as is and just copy that output file into the desired directory once processed. Here is how you can do that.

    mix.js('resources/js/app.js', 'public/js')
        .sass('resources/scss/app.scss', 'public/css')
        .webpackConfig({
            plugins: [
                new MonacoWebpackPlugin({
                    languages: ['css', 'html', 'javascript', 'json', 'scss', 'typescript'],
                }),
            ],
        })
        .copy('SOURCE_PATH', 'DESTINATION_PATH');
    

    Define all the files you want to copy, using the chained copy function call. Alternatively, There is another laravel-mix method copyDirectory(fromDir, toDir) to copy the entire directory.

    For more advanced usage, You can perform post-processing on assets manually from the mix Promise resolution as given,

    mix.then(function () {
      //Perform post-processing on generated assets
    }) //Will be triggered each time Webpack finishes building.
    

    Here, You'll have a free hand to copy/delete/rename assets using fs module,

    Alternatively, the vendor extraction may help. You can get the Monaco editor to the vendor.js file using extract() by passing the library name in the array. It will output the vendor.js file into the public directory and then after copy() function may help you to copy that file.