Vue JS Browserify to Webpack Conversion
in Blog,
by Marnix Kok
last published on 24 November 2021
Converting your projects from one fundamental framework to another is never fun, but sometimes you have to combat the bitrot and step out and "just do it". So here we are, doing it!
One of the projects I've been working on in my spare time has a frontend build pipeline involving Browserify. Unfortunately it seems like most of the dependencies involved with this project haven't seen a proper release in a wee while. On the other hand, webpack has been taking off and has matured considerably in the last few years. Other than being the technology du jour, it also has a number of benefits related to intelligently shaking code from the tree that are more complicated to accomplish with Browserify.
With all that in mind, I moved my project across. Below an overview of some files you can use as a template for your own project and some steps you must apply to your code to lift it onto this new build platform.
Preparing your packages
Make sure your `package.json` has at least the following `devDependencies` (it would worthwhile updating to the latest versions of these when you copy/paste them across):
"devDependencies": { "@babel/core": "^7.16.0", "@babel/preset-env": "^7.16.0", "@babel/plugin-transform-runtime": "^7.16.0", "@babel/runtime": "^7.16.3", "babel-loader": "^8.2.3", "vue-loader": "^15.9.8", "vue-template-compiler": "^2.6.14", "core-js": "^3.19.1", "npm-run-all": "^2.3.0", "sass": "^1.26.3", "webpack": "^5.64.0", "webpack-cli": "^4.9.1", "webpack-dev-server": "^4.5.0" }
Make sure to match the version of `vue-template-compiler` with the version of VueJS you've specified in your `dependencies` list.
Also add the following line to the top-level values of your package.json file:
"sideEffects": false,
Of course it's also a good idea to clean up your browserify-related dependencies, especially if there are previous Babel versions included that may interfere with the running of your application.
In most of my projects I am building off of an existing (purchased) HTML/SCSS template, this makes it so I don't usually include SCSS styling in my VueJS templates, but manage them separately. This means however that I run a separate `sass` build-step.
Webpack configuration
The following webpack configuration uses `./src/main.js` as your entrypoint, instructs to write the output into `assets/dist/`. Optimisations include explicitly telling webpack that your files generate no sideEffects (put stuff on the global namespace instead of strictly import/exporting) and the removal of unused exports.
There are two loaders, one for transpiling Javascript, and another one for the Vue templates.
Lastly, because I don't like the relative path includes in NodeJS I always make sure NODE_PATH has `.` as its value. In webpack we have to specify the lookup path in the `resolve/modules` JSON value, by adding '.' as an an element.
const { VueLoaderPlugin } = require("vue-loader"); const path = require("path"); module.exports = { entry: { main: "./src/main.js", }, output: { filename: "build.js", path: path.resolve(__dirname, "assets/dist"), }, optimization: { usedExports: true, sideEffects: false }, module: { rules: [ { test: /\.js$/, exclude: /node_modules/, use: { loader: "babel-loader", }, }, { test: /\.vue$/, loader: "vue-loader", }, ], }, plugins: [ new VueLoaderPlugin(), ], resolve: { alias: { "vue$" : "vue/dist/vue.esm.js", }, extensions: ["*", ".js", ".vue", ".json"], modules: [".", "./node_modules"] }, };
Setup babel.config.js
Now we set up the configuration for the Javascript transpiler called Babel. It's quite unremarkable:
module.exports = { sourceType: "unambiguous", presets: [ ["@babel/preset-env", { useBuiltIns: "usage", corejs: 3 }] ], plugins: [ '@babel/plugin-transform-runtime' ] };
Code changes
If like me, you had been using the CommonJS `require` function to include other pieces of code, the major change you'll have to go through is to replace all of these with their `import` variant.
Similarly you'll have to change `module.exports` to `export` functionality. There are many great resources online that show you how to do it so I won't elaborate on that here.
Compilation
Because most of my VueJS projects are embedded in a larger ExpressJS application running webpack as a development server doesn't always work out that well. Instead we're going to be using the following NPM script rules to start ExpressJS and watch for JS and SCSS changes in the background:
"scripts": { "dev": "cross-env NODE_PATH=. NODE_ENV=development npm-run-all --parallel watchscss watchwebpack express", "watchwebpack": "webpack-cli watch --mode development", "build": "webpack-cli --mode production && node_modules/sass/sass.js --style=compressed assets/stylesheets/all.scss:assets/dist/all.css", "prodlike": "npm-run-all build express", "watchscss": "node_modules/sass/sass.js --watch assets/stylesheets/all.scss:assets/dist/all.css", "express": "NODE_ENV=development NODE_PATH=. node index.js" }
Then on the command line (or in your favourite IDE) you can execute the following to run your server in development mode:
$ npm run dev
.. or for starting up a production-like build (great for testing before pushing) run the following:
$ npm run prodlike
That was it, pretty easy overall, but sometimes the documentation can feel a bit scattered, making moving across to a new technology a bit daunting. Hope this helps, get in touch if you have any questions.