Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Could we remove declaration from Vite section #1

Open
baseplate-admin opened this issue Apr 2, 2023 · 9 comments
Open

Could we remove declaration from Vite section #1

baseplate-admin opened this issue Apr 2, 2023 · 9 comments
Assignees
Labels
enhancement New feature or request

Comments

@baseplate-admin
Copy link
Contributor

baseplate-admin commented Apr 2, 2023

Hi there,

Thanks for making this ( i was the one who asked you the question in the forum )

//vite.config.js
import { defineConfig } from 'vite'
import djangoVite from 'django-vite-plugin'

export default defineConfig({
    plugins: [
        djangoVite([
            // Can we not declare the files in here?
            'home/js/app.js',
            'home/css/style.css',
        ])
    ],
});

So i was thinking can we remove this section so that it can auto detect the path when we call the template tag.

with all being said Mashallah for this package brother and ramadan mubarak

@protibimbok
Copy link
Owner

This section is for providing the build entrypoints to the vite build tools.
Removing this configuration is not worth the effort. We'll have to scan through all template files and collect the used assets and so on. Even after this, there's a possibility of dynamic assets, which is impossible to track with certainty. Another approach might be just to compile everything. Given that the static file count can be really large, this couldn't be any less optimal.

But currently I am working on a helper function that'll help the developers to pass these assets more elegantly.

// Possible syntax
...
import { inputHelper } from 'django-vite-plugin'
djangoVite(inputHelper([
     '@app': {
          'dir1': ['file1.js', 'file2.js'],
          'dir2': {}
      }
]))
...

Even this does not seem like that much of a help. But there's place for improvements.

Thank you for your feedback.
"Ramadan Kareem"

@baseplate-admin
Copy link
Contributor Author

Even after this, there's a possibility of dynamic assets, which is impossible to track with certainty.

I dont get this. Dynamic assets?

Given that the static file count can be really large, this couldn't be any less optimal.

Forgive me but Doesn't vite offer source imports ?

Even this does not seem like that much of a help. But there's place for improvements.

One possibility i see is aliasing all page under one namespace.

import { inputHelper } from 'django-vite-plugin'
djangoVite(inputHelper([     
          'home_page': ['file1.js', 'file2.js'],
          'another_page': {}     
]))
প্রতিবিম্বক। nice name :]

@protibimbok
Copy link
Owner

I dont get this. Dynamic assets?

Any link to css/js you send from the view (see the example project.).

def home(req):
    return render(req, 'index.html', {
        'dyn_js' : 'a_dynamic_js.js',
        'dyn_css' : 'a_dynamic_css.css',
        'dyn_attr': 'A dynamic attr'
    })

Forgive me but doesn't vite offer source imports ?

It's about passing the inputs to rollupOptions everything you give here will result in a separate output file - which is not optimal. But if you want to do this, you may just use glob

//vite.config.js
import { defineConfig } from 'vite'
import djangoVite from 'django-vite-plugin'
import glob from 'glob'

export default defineConfig({
    plugins: [
        djangoVite(glob.sync(
             '/**/*.{js,css}'
        ))
    ],
});

And the inputHelper is still under consideration.
Thank you

@protibimbok protibimbok reopened this Apr 4, 2023
@protibimbok protibimbok added the enhancement New feature or request label Apr 4, 2023
@protibimbok
Copy link
Owner

As I've stated earlier, to remove this we'll have to scan through all of the template files to get the references. Even though it's not the best way to go, but seems like I should give it a try...

@protibimbok protibimbok self-assigned this Apr 4, 2023
@baseplate-admin
Copy link
Contributor Author

baseplate-admin commented Apr 4, 2023

As I've stated earlier, to remove this we'll have to scan through all of the template files to get the references. Even though it's not the best way to go, but seems like I should give it a try...

thanks a bunch for reconsidering..

def home(req):
    return render(req, 'index.html', {
        'dyn_js' : 'a_dynamic_js.js',
        'dyn_css' : 'a_dynamic_css.css',
        'dyn_attr': 'A dynamic attr'
    })

I have never seen ( nor used ) this pattern from django app. Django ( views ) is not a good candidate to write logics for assets IMHO ( templates is ).

And the inputHelper is still under consideration.

Thanks again.

Lmk if you need any help ( i dont know much but i will try to help )

Love from Bangladesh :D

@protibimbok
Copy link
Owner

I have never seen ( nor used ) this pattern from django app. Django ( views ) is not a good candidate to write logics for assets IMHO ( templates is ).

Neither did I. But when you write something for mass developer you shouldn't take away any feature.

Thank you for the support.

@jbuerklin
Copy link

I added a function to my vite.config.js that scans through the project directory in order to find *.html files with {% vite %} template tags. It works quite well for my uses. You could also easily add entrypoints manually if needed (e.g. for dynamic assets as discussed earlier)

import { defineConfig } from 'vite'
import { djangoVitePlugin } from 'django-vite-plugin'
import fs from 'fs'
import path from 'path'

/**
 * Searches through the project's HTML files and extracts the entrypoints from the {% vite %} tag.
 *
 * @returns {Array<string>} list of entrypoints
 */
const findEntrypoints = () => {
    let folders = ['.']
    let files = []
    while (folders.length > 0) {
        const folder = folders.pop()
        if (
            ['node_modules', 'venv', 'vite_build', 'static'].includes(
                path.basename(folder)
            )
        ) {
            continue
        }
        let results
        try {
            results = readDirectory(folder)
        } catch (error) {
            continue
        }
        files = files.concat(results.files)
        folders = folders.concat(results.folders)
    }
    const entrypoints = new Set()
    for (const file of files) {
        if (file.endsWith('.html')) {
            const content = fs.readFileSync(file, 'utf8')

            const matches = content.matchAll(
                /{%\s+vite\s+('|")(.+?)\1\s+.*?%}/g
            )
            for (const match of matches) {
                entrypoints.add(match[2])
            }
        }
    }
    const entrypointsList = Array.from(entrypoints)
    console.log(`found entrypoints:\n${entrypointsList.join('\n')}`)
    return entrypointsList
}

/**
 * Parses the given directory and extracts a list of all files and all subdirectories.
 *
 * @typedef ReadDirectoryReturnObject
 * @property {Array<string>} folders - list of all subdirectories
 * @property {Array<string>} files - list of all files
 * @param {string} dirPath - directory path to read
 * @returns {ReadDirectoryReturnObject} two list; all files and all subdirectories
 */
const readDirectory = (dirPath) => {
    const data = fs.readdirSync(dirPath)
    const folders = []
    const files = []
    data.forEach((file) => {
        const filepath = path.join(dirPath, file)
        if (file.includes('.')) {
            files.push(filepath)
        } else {
            folders.push(filepath)
        }
    })
    return { folders, files }
}

export default defineConfig({
    plugins: [
        djangoVitePlugin({
            input: findEntrypoints(),
            addAliases: true,
        }),
    ],
})

@protibimbok
Copy link
Owner

protibimbok commented Nov 25, 2023

This is amazing. Some suggestions:

  1. No need to scan in dev mode. Only scan during the build command.
  2. Create a caching system. (I.e. storing the included files in a file as json and instead of scanning every time for {% vite %} you will scan only for the changed files)
  3. Maybe do it in Python
  4. Maybe use multi-threading as file count can be really large.

After completing these, please create a pull request.

Keep this functionality in a new file vite/src/lookup.ts and export from there.

@elnygren
Copy link

elnygren commented Mar 19, 2024

I'm using this library without the django-vite-plugin JS side vite plugin. My setup is the following:

  1. Vite runs completely without Django or any knowledge of it
  2. .hotfile is created by hand (content: http://127.0.0.1:5173)
  3. Django side settings:
DJANGO_VITE_PLUGIN = {
    # 'npm run build' output directory; collectstatic will copy all files from here
    # must match vite.config.ts -> build -> outDir
    "BUILD_DIR": "src/static/vite",
    # prefix has to point to the outDir with manifest.json
    "BUILD_URL_PREFIX": "/static/vite/",
    # we don't keep the source code in static dirs so this can be False
    "STATIC_LOOKUP": False,
    "MANIFEST": "src/static/vite/manifest.json",  # can drop this with vite5
}
  1. Vite side settings:
export default defineConfig(({ mode }) => ({
  plugins: [react()],
  server: {
    host: '127.0.0.1',  // django is calling 127.0.0.1 instead of localhost
  },
  base: mode === 'development' ? '/' : '/static/vite/', // DJANGO_VITE_PLUGIN->BUILD_URL_PREFIX
  build: {
    manifest: true,  // generate manifest.json in outDir
    outDir: 'src/static/vite',  // must match DJANGO_VITE_PLUGIN-> BUILD_DIR
    rollupOptions: {
      input: [...glob.sync('src/vite/**/*.{ts,tsx,css}')], // <- where vite-processed code lives
    },
  },
}))

Sure the downside is having to keep some settings in sync by hand... but that's a lot simpler than having Django-magic-code inside Vite and needing Django to do a vite build (think about CI/CD and containers...).

Not sure why I'd want more complexity than that? 🤔

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants