ChrisNY
ChrisNY

Reputation: 4217

Get Laravel Mix to transpile JS from different path

I'm using Laravel Mix, and it nicely simplifies using WebPack & Babel to transpile advance JS features down to older browsers - EXCEPT! (and I'm going crazy here) ... it only works for me if I put the JS to be transpiled into the directory they recommend.

The basic recommended "webpack.mix.js" setup is mix.js(['resources/js/app.js'], 'public/js/app.js'); where the first argument can be a single file or an array of files to be transpiled.

The default resources/js/app.js requires several standard modules, like vue, lodash, axios. Works great. Then in app.js I want to require some additional sources from vendor/xxxx/assets/js/xx.js - but I get an error: Unknown plugin "transform-object-rest-spread" specified - which means it can't find the babel plugin, which is definitely installed. It's something with the path.

If I copy that xx.js into the resources/jsand then require it in app.js, no problem.

I've used mix.webpackConfig to add the module path vendor/xxxx/assets/js, I've used alisas to set 'xx$': path.resolve(__dirname,"vendor/xxxx/assets/js/xx.js", and tried to mess around with the babel options, both in .babelrc & the webpackConfig option object.

The one version of the final webpack config is below - believe me, I've played with many variants, I know this isn't the one right one, but nothing has worked to import/require/transpile any file outside of either node_modules (vue) or /resources/js (app.js, which can also require other files within that directory). Any ideas would be great!

{ context: 'C:\\www\\Laravels\\lsbb-5-3\\laravel', entry: { '/mixed/js/es6': [ 'C:\\www\\Laravels\\lsbb-5-3\\laravel\\resources\\js\\app.js', 'C:\\www\\Laravels\\lsbb-5-3\\laravel\\vendor\\xxxx\\js\\xx.js' ] }, output: { path: 'C:\\www\\Laravels\\lsbb-5-3\\laravel\\public', filename: '[name].js', chunkFilename: '[name].js', publicPath: '/' }, module: { rules: [ { test: /\.html$/, loaders: [ 'html-loader' ] }, { test: /(\.(png|jpe?g|gif)$|^((?!font).)*\.svg$)/, loaders: [ { loader: 'file-loader', options: { name: [Function: name], publicPath: '/' } }, { loader: 'img-loader', options: { enabled: true, gifsicle: {}, mozjpeg: {}, optipng: {}, svgo: {} } } ] }, { test: /(\.(woff2?|ttf|eot|otf)$|font.*\.svg$)/, loader: 'file-loader', options: { name: [Function: name], publicPath: '/' } }, { test: /\.(cur|ani)$/, loader: 'file-loader', options: { name: '[name].[ext]?[hash]', publicPath: '/' } }, { test: /\.jsx?$/, exclude: /(node_modules|bower_components)/, use: [ { loader: 'babel-loader', options: { cacheDirectory: true, presets: [ [ 'env', { modules: false, targets: { browsers: [ '> 2%' ], uglify: true } } ] ], plugins: [ 'transform-object-rest-spread', [ 'transform-runtime', { polyfill: false, helpers: false } ], [ 'transform-object-rest-spread' ] ] } } ] }, { test: /\.css$/, loaders: [ 'style-loader', 'css-loader' ] }, { test: /\.s[ac]ss$/, exclude: [], loaders: [ 'style-loader', 'css-loader', 'sass-loader' ] }, { test: /\.less$/, exclude: [], loaders: [ 'style-loader', 'css-loader', 'less-loader' ] } ] }, plugins: [ FriendlyErrorsWebpackPlugin { compilationSuccessInfo: {}, onErrors: undefined, shouldClearConsole: true, formatters: [ [Function: format], [Function: format], [Function: format] ], transformers: [ [Function: transform], [Function: transform], [Function: transform] ] }, DefinePlugin { definitions: { 'process.env': { NODE_ENV: '"development"' } } }, LoaderOptionsPlugin { options: { minimize: false, options: { context: 'C:\\www\\Laravels\\lsbb-5-3\\laravel\\node_modules\\laravel-mix\\src\\builder', output: { path: './' } }, test: { test: [Function: test] } } }, ManifestPlugin {}, CustomTasksPlugin {}, BuildCallbackPlugin { callback: [Function] }, { options: { title: 'Laravel Mix', alwaysNotify: true, hint: undefined, contentImage: 'C:\\www\\Laravels\\lsbb-5-3\\laravel\\node_modules\\laravel-mix\\icons\\laravel.png' }, lastBuildSucceeded: false, isFirstBuild: true } ], stats: { hash: false, version: false, timings: false, children: false, errorDetails: false, chunks: false, modules: false, reasons: false, source: false, publicPath: false }, performance: { hints: false }, devtool: 'eval-source-map', devServer: { headers: { 'Access-Control-Allow-Origin': '*' }, contentBase: 'C:\\www\\Laravels\\lsbb-5-3\\laravel\\public', historyApiFallback: true, noInfo: true, compress: true, quiet: true }, resolve: { extensions: [ '*', '.js', '.jsx', '.vue' ], alias: { 'vue$': 'vue/dist/vue.common.js', 'xx$': 'vendor/xxxx/js/xx.js', modules: [ 'node_modules', 'vendor/xxxx/js' ] } }

Upvotes: 0

Views: 1140

Answers (2)

Friendly Code
Friendly Code

Reputation: 1645

The solution as found over on Github is to add this to your mix file:

mix.webpackConfig({ resolve: { symlinks: false } })

🙌

Upvotes: 0

ChrisNY
ChrisNY

Reputation: 4217

AHH! After days & nights, I finally figured it out! The files in question are kind of like a library that I use in several projects, so I just symlink the directory into the project. I've been doing that for YEARS without problems with all kinds of build & project tools, so I didn't give it a thought.

BUT it turns out that Babel (or Babel in WebPack) breaks when it tries to follow symlinks!

So I can't say I found a solution, but I found a suitable work-around. The first step of my build process I just copy the files from the source directory into the project directory. Thats disgusting but actually works fine for my purposes - which is to just edit the library in a single location so I don't wind up with different versions. So I can just edit the source & build & voila!

If you have this problem and want to do it right, there are supposed to be additional plugins that help babel resolve these path issues but once I figured out what the problem was, I couldn't be bothered. Good luck to anyone else!

Upvotes: 1

Related Questions