AccordBox / python-webpack-boilerplate

Django Webpack boilerplate & Flask Webpack boilerplate
https://python-webpack-boilerplate.rtfd.io
MIT License
167 stars 20 forks source link

Add option to allow user to create `package.json` at the root directory #17

Closed michael-yin closed 2 years ago

michael-yin commented 2 years ago
  1. Update webpack.common.js
  2. Update package.json
  3. Use post-generate to move the frontend config files from frontend directory to root directory.
  4. Add notes to Doc
FilipWozniak commented 2 years ago

What is the use case for running NPM command at root directory? Or, let me rephrase that question - what are the benefits comparing to executing NPM command at frontend directory?

By the way, I've been meaning to ask the following question.

Hypothetically, let's say that I have a pretty standard configuration of python-webpack-boilerplate (Wagtail, Webpack and Vue with live reloading feature enabled). I want to create a relatively huge and modular application. For this purpose, I usually create an apps folder at the root of the project.

├─── frontend
    └─── src
        ├─── application
        ├─── components
        └─── styles
├─── apps
    ├─── [django-application-1]
    ├─── [django-application-2]
    └─── [django-application-3]
└─── [project-name]
    ├─── home
    ├─── [project-name]
    ├─── search
    ├─── manage.py
    ├─── requirements.txt
    ├─── db.sqlite3
    └─── Dockerfile

Suppose that every application located in apps folder is more or less reusable, so it has its own repository. Moreover, each of these applications contains a lot of front-end files (mainly .Vue components). Theoretically, everything is fine. I mean, as long as I keep all the front-end files in the frontend folder. It's just that.. I don't want to. These files should fall into each individual applications, as illustrated below.

├─── frontend
    └─── src
        ├─── application
        ├─── components
        └─── styles
├─── apps
    ├─── [django-application-1]
        └─── frontend
            └─── src
                ├─── application
                ├─── components
                └─── styles
    ├─── [django-application-2]
    └─── [django-application-3]
└─── [project-name]
    ├─── home
    ├─── [project-name]
    ├─── search
    ├─── manage.py
    ├─── requirements.txt
    ├─── db.sqlite3
    └─── Dockerfile

It brings us to two potential solutions.

The first one - each application of Django should be treated like a separate Node application. It would be very uncomfortable given the fact that each individual application would have to include node_modules folder and be complied separately. There would be no problem with two or three Node applications, but having more than five would be unbearable.

The second one - make frontend folder see the files from each individual Django applications, since otherwise how can I compile? The only reasonable solution I came up with is creation of symbolic links.

ln -sfn ../[wagtail-project]/apps/[django-application]/frontend/src/application/* ../[wagtail-project]/frontend/src/application/
ln -sfn ../[wagtail-project]/apps/[django-application]/frontend/src/components/* ../[wagtail-project]/frontend/src/components/
ln -sfn ../[wagtail-project]/apps/[django-application]/frontend/src/styles/* ../[wagtail-project]/frontend/src/styles/

I tested it, and it's working, but my question is, may it be achieved easier? How can I simultaneously compile files from frontend folder and from each individual Django application? Perhaps some entry in webpack.config.js file could solve this issue?

I assume that including another Path in webpack.config.js file is not enough?

include: [
  Path.resolve(__dirname, "../src"),
  Path.resolve(__dirname, "../../apps/**/frontend/src"),
]

Am I missing something?

FilipWozniak commented 2 years ago

Finally, I'm pretty sure that I solved that issue!

Before (webpack.common.js)

const getEntryObject = () => {
  const entries = {};
  glob.sync(Path.join(__dirname, "../src/application/*.js")).forEach((path) => {
    const name = Path.basename(path, ".js");
    entries[name] = path;
  });
  return entries;
};

After (webpack.common.js)

const getEntryObject = () => {
  const entries = {};
  glob.sync(Path.join(__dirname, "../src/application/*.js")).forEach((path) => {
    const name = Path.basename(path, ".js");
    entries[name] = path;
  });
  glob.sync(Path.join(__dirname, "../../apps/**/frontend/src/application/*.js")).forEach((path) => {
    const name = Path.basename(path, ".js");
    entries[name] = path;
  });
  return entries;
};

Before (webpack.config.dev.js & webpack.config.watch.js)

module: {
  rules: [
    include: [
      Path.resolve(__dirname, "../src"),
    ],
  },
],
new StylelintPlugin({
  files: [
      Path.resolve(__dirname, "../src/**/*.s?(a|c)ss"),
  ]    
}),
new ESLintPlugin({
  extensions: "js",
  emitWarning: true,
  files: [
      Path.resolve(__dirname, "../src"),
  ]
}),

After (webpack.config.dev.js & webpack.config.watch.js)

module: {
  rules: [
    include: [
      Path.resolve(__dirname, "../src"),
      Path.resolve(__dirname, "../../apps/**/frontend/src"),
    ],
  },
],
new StylelintPlugin({
  files: [
      Path.resolve(__dirname, "../src/**/*.s?(a|c)ss"),
      Path.resolve(__dirname, "../../apps/**/frontend/src/**/*.s?(a|c)ss"),
  ]
}),
new ESLintPlugin({
  extensions: "js",
  emitWarning: true,
  files: [
      Path.resolve(__dirname, "../src"),
      Path.resolve(__dirname, "../../apps/**/frontend/src"),
  ]
}),

Before (webpack.config.prod.js)

module: {
  rules: [
    include: [
      Path.resolve(__dirname, "../src"),
    ],
  },
],

After (webpack.config.prod.js)

module: {
  rules: [
    include: [
      Path.resolve(__dirname, "../src"),
      Path.resolve(__dirname, "../../apps/**/frontend/src"),
    ],
  },
],

Finally, front-end can be managed the way it should 😃

image
michael-yin commented 2 years ago

@FilipWozniak

Even I prefer to put all frontend stuff in one directory, put them into individual applications seems interesting approach.

Good work!