Skip to content

Instantly share code, notes, and snippets.

@lsapan
Last active December 29, 2022 10:47
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save lsapan/bdc1fbba71058cc337abc181a84b4f49 to your computer and use it in GitHub Desktop.
Save lsapan/bdc1fbba71058cc337abc181a84b4f49 to your computer and use it in GitHub Desktop.
Using Vue CLI to start a Vue frontend for use with a Django backend

Using Vue CLI to start a Vue frontend for use with a Django backend

Note: This guide has been updated for use with @vue/cli version 4! Please make sure you're using the latest version of @vue/cli.

When it comes to starting new Vue projects, you can't really beat Vue CLI. The Vue team has done a phenomenal job of making an easy-to-use tool for getting started with reasonable defaults. If you're using Django though, you may not have the easiest time getting its static system and webpack to play well together.

A good chunk of this is applicable to any webpack-compiled frontend and Django, but we'll focus specifically on the steps involved with Vue CLI.

As a quick heads up: this tutorial assumes you're creating your Vue project in a folder named frontend inside of your Django project folder. If you want it named something else, or want it in a different folder, just update the paths accordingly.

Create the Vue project

If you haven't already, install Vue CLI with npm i -g @vue/cli.

Run vue ui and create a new project named frontend in your Django project folder. As far as presets and features, you do you.

Edit the Vue project

Open your Django app in your favorite editor so we can make some changes.

Delete the following folders/files from the frontend folder:

  • public/
  • .gitignore (you're hopefully already using git for Django)
  • README.md

In the frontend folder, run npm i --save-dev webpack-bundle-tracker.

Update your vue.config.js file to look like this:

const BundleTracker = require('webpack-bundle-tracker')

// Change this to match the path to your files in production (could be S3, CloudFront, etc.)
const DEPLOYMENT_PATH = '/static/dist/'

module.exports = {
    publicPath: process.env.NODE_ENV === 'production' ? DEPLOYMENT_PATH : 'http://localhost:8080/',
    outputDir: '../(name of Django app)/static/dist',

    devServer: {
        public: 'localhost:8080',
        headers: {
            'Access-Control-Allow-Origin': '*',
        },
    },

    configureWebpack: {
        plugins: [
            new BundleTracker({ path: __dirname, filename: 'webpack-stats.json' }),
        ],
    },
}

Configure Django

Install django-webpack-loader using pip.

In settings.py add WEBPACK_LOADER under your static settings:

STATIC_URL = '/static/'

WEBPACK_LOADER = {
    'DEFAULT': {
        'STATS_FILE': os.path.join(BASE_DIR, 'frontend', 'webpack-stats.json'),
    }
}

Also be sure to add webpack_loader to your list of INSTALLED_APPS.

Add your bundle to a template

Almost there! Add this to the bottom of your body tag:

{% render_bundle "chunk-vendors" %}
{% render_bundle "app" %}

That's it!

You can now run npm run dev to compile your app with hot module replacement, or npm run build to create a production build.

Update your .gitignore

You'll probably want to add these lines to your .gitignore:

node_modules/
dist/
package-lock.json
webpack-stats.json
@EugeneDae
Copy link

Alternative approach that does not need any plugins. (Not advocating against the approach described here, which has its advantages, I only wanted to explore a plugin-less alternative).

@8area8
Copy link

8area8 commented Dec 20, 2020

The explanation misses half of the things, we have nothing to make it work after reading.

@chinyasstuva
Copy link

thanks, all worked well

@mejl
Copy link

mejl commented Jun 12, 2021

Doesn't work, I downloaded 0.7.0, but when I run django the vue doesn't show up. I am also running the vue.

@mejl
Copy link

mejl commented Mar 1, 2022

How can you use django-webpack-loader for 2 different components.

I want to use each component separately for a view/template.


I found this code at https://shumingxu.com/posts/vue-django-multi-page/#vue-js-webpack-setup, but I modified it just a little.

const BundleTracker = require("webpack-bundle-tracker");
module.exports = {
    publicPath: "http://127.0.0.1:8080/",
    outputDir: './dist/',
    chainWebpack: config => {
        config.optimization
            .splitChunks(false)
        config
            .plugin('BundleTracker')
            .use(BundleTracker, [{filename: '../vue3/webpack-stats.json'}])
        config.resolve.alias
            .set('__STATIC__', 'static')
        config.devServer
            .public('http://0.0.0.0:8080')
            .host('0.0.0.0')
            .port(8080)
            .hotOnly(true)
            .watchOptions({poll: 1000,})
            .https(false)
            .headers({"Access-Control-Allow-Origin": ["\*"]})
    },
    pages: {
        order: 'src/pages/View1/main.js',
        store: 'src/pages/View2/main.js',
    }
};

The problem with this code is that it gives me options has an unknown property 'watchOptions', and if I delete watchOptions it will give me that hotOnly is unknown as-well. And if I delete hotOnly some other stuff was unknown also I think.


In package.json it says that I have "webpack-bundle-tracker": "^1.4.0"

@lsapan
Copy link
Author

lsapan commented Mar 1, 2022

@mejl try downgrading to:
"webpack-bundle-tracker": "^0.4.2-beta"

You can configure different pages with the WEBPACK_LOADER config, instead of using a single default one.

@mejl
Copy link

mejl commented Mar 2, 2022

@lsapan I tried "webpack-bundle-tracker": "^0.4.2-beta", and still get the same error. I deleted node_modules, and did npm install.

Still not working.


I found another tutorial, but that one has watchOptions also. https://medium.com/js-dojo/vue-django-best-of-both-frontends-701307871478

The vue.config.js looks like this on the other tutorial.
const BundleTracker = require("webpack-bundle-tracker");

const pages = {
    'vue_app_01': {
        entry: './src/main.js',
        chunks: ['chunk-vendors']
    },
    'vue_app_02': {
        entry: './src/newhampshir.js',
        chunks: ['chunk-vendors']
    },
}

module.exports = {
    pages: pages,
    filenameHashing: false,
    productionSourceMap: false,
    publicPath: process.env.NODE_ENV === 'production'
        ? ''
        : 'http://localhost:8080/',
    outputDir: '../django_vue_mpa/static/vue/',

    chainWebpack: config => {

        config.optimization
            .splitChunks({
                cacheGroups: {
                    vendor: {
                        test: /[\\/]node_modules[\\/]/,
                        name: "chunk-vendors",
                        chunks: "all",
                        priority: 1
                    },
                },
            });

        Object.keys(pages).forEach(page => {
            config.plugins.delete(`html-${page}`);
            config.plugins.delete(`preload-${page}`);
            config.plugins.delete(`prefetch-${page}`);
        })

        config
            .plugin('BundleTracker')
            .use(BundleTracker, [{filename: '../vue_frontend/webpack-stats.json'}]);

        config.resolve.alias
            .set('__STATIC__', 'static')

        config.devServer
            .public('http://localhost:8080')
            .host('localhost')
            .port(8080)
            .hotOnly(true)
            .watchOptions({poll: 1000})
            .https(false)
            .headers({"Access-Control-Allow-Origin": ["*"]})

    }
};

@lsapan
Copy link
Author

lsapan commented Mar 2, 2022

@mejl just to clarify, did you try the exact config in this tutorial and run into that error? It sounds like you're running into that because of the other config.

@mejl
Copy link

mejl commented Mar 3, 2022

@lsapan Yes, I commented out the old one and copied vue.config.js from this tutorial and pasted to mine, but changed the file-path so it goes to my main.js in vue.config.js const pages.

I don't understand why watchOptions is not working when I'm using the same webpack-bundle-tracker version as the tutorial.
When I'm doing yarn serve or npm run serve It only goes to 1% before the error shows up.

ERROR ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.

Here is the full error:

ERROR ValidationError: Invalid options object. Dev Server has been initialized using an options object that does not match the API schema.
- options has an unknown property 'watchOptions'. These properties are valid:
object { allowedHosts?, bonjour?, client?, compress?, devMiddleware?, headers?, historyApiFallback?, host?, hot?, http2?, https?, ipc?, liveReload?, magicHtml?, onAfterSetupMiddleware?, onBeforeSetupMiddleware?, onListening?, open?, port?, proxy?, server?, setupExitSignals?, setupMiddlewares?, static?, watchFiles?, webSocketServer?

Trace back:

at validate (.../vue3/node_modules/webpack-dev-server/node_modules/schema-utils/dist/validate.js:115:11)
at new Server (.../vue3/node_modules/webpack-dev-server/lib/Server.js:232:5)
at serve (.../vue3/node_modules/@vue/cli-service/lib/commands/serve.js:183:20)
at processTicksAndRejections (node:internal/process/task_queues:96:5)

vue3 is the name of the vue project
... is for example /User/name/folder/djangoProjectFolder/

@lsapan
Copy link
Author

lsapan commented Mar 3, 2022

@mejl keep in mind that watchOptions has nothing to do with the bundle tracker. It sounds like your version of the dev server may not support that setting. I’d recommend checking its version, and the docs for that specific version. That said, this isn’t super pertinent to this gist so I’d suggest moving this question to StackOverflow if you’re still having issues. Good luck!

@mejl
Copy link

mejl commented Mar 4, 2022

@lsapan I changed my package.json, similar to the tutorial https://github.com/ilikerobots/django-vue-mpa/blob/master/vue_frontend/package.json

The problem was that the vue cli 5 used v4 of webpack that doesn't have watchOptions, so I changed to vue cli 4.5.0 as the tutorial had and I had to changed some other stuff as well. Vue cli 4.5.0 are using https://webpack-3.cdn.bcebos.com/configuration/dev-server/#devserver-watchoptions- So now it works. Thanks for your help.

How I did it
npm install -g @vue/cli@4.5.0

to get 4.5.0 in your already existing vue project

I changed this in package.json in devDependencies

"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-service": "^4.5.0",

before I think I had 5.0.1

Then I deleted node_modules and package-lock.json
after that I wrote in the terminal

yarn
and after that
npm install

@hatamiarash7
Copy link

Great 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment