Skip to content

Add webpack for static asset generation #88

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

Merged
merged 2 commits into from
Feb 25, 2020

Conversation

hoetmaaiers
Copy link
Collaborator

By adding Webpack to the theme development stack, some tasks become available or easier.

  1. It is possible to write scss that compiles to css. Scss has numorous advantages over vanilla css.
  2. Additional steps will be added to ensure vendor prefixes are added to the css output. This ensures browser compatibility.
  3. With Webpack javascript also can be compiled from modern (e.g. ES2020) into browser compatible javascript.

Via package.json all necessary dependencies can be installed:

yarn install

After installation 2 scripts are available:

  • yarn build:dev: which spins up a development server and makes the docs demo available on localhost:1919. When changing theme.scss, theme.js or any './docs//*.rst', './docs//*.py' file, the demo at localhost:1919 will be reloaded.
  • yarn build:production: this generates production ready assets from theme.scss and theme.js into the the directory.

@jorisvandenbossche
Copy link
Member

So to test this out, I did:

Install yarn (which seems to be in conda-forge)

conda install yarn

Then run from the root of the repo:

yarn install

Then I ran

yarn build:dev

which built the demo docs, I opened this in http://localhost:1919. And if I then made a change in one of the rst files, this automatically triggered to run sphinx again, and I could refresh the rendered html version to see the change.

This seems really nice for working on the theme (as long as the sphinx site doesn't take a long time to build, which is now the case for the demo docs. For the actual pandas docs you would probably not want such automatic trigger, as building it can take a while).

@stijnvanhoey @choldgraf any concerns in adding this?
It certainly adds some tech that most python developers are not familiar with. But I could test it in like 15 min (description above), so it seems rather easy, if we add good contributing guidelines.
As far as I understand, the actual generated css/js files will still be included in the repo, so installing it with pip directly from github master (as projects now do) should still work.

@jorisvandenbossche
Copy link
Member

@hoetmaaiers running yarn build:production gives an error (I don't know if that is already supposed to work?): "Error: Cannot find module 'optimize-css-assets-webpack-plugin'"

@choldgraf
Copy link
Collaborator

I can give a shot at the instructions and see how confusing it is. To me the biggest danger is that our core dev audience probably doesn't use yarn. If we use this we should make sure to document well how it works and make sure it isn't unstable for different install environments etc

@jorisvandenbossche
Copy link
Member

jorisvandenbossche commented Feb 15, 2020

Yes, I fully agree we need to be careful about introducing technical hurdles. Some additional points:

  • AFAIU, it is only needed when developing the theme, not when using the theme for another project like jupyterhub (which is I think a necessary condition)
  • I could easily install it with conda (so we can also include it a dev environment yml file), but we should have instructions for non-conda people as well. The instructions at https://yarnpkg.com/getting-started/install are already not very clear I find (it seems to point to an old version of yarn that you need to install with which you can then install a newer version of yarn locally for the project?)
  • We could also have some make shortcuts for people that are more familiar with that than with yarn. Eg a make html could also ensure to regenerate the css/js files, similarly to what yarn build:dev does.

I can give a shot at the instructions and see how confusing it is

That would be very useful. I think the instructions are basically what I put in #88 (comment)

@@ -0,0 +1,387 @@
/*
* nature.css_t
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the auto-generated file?
If so, can we have a comment at the top saying this?

Copy link
Collaborator Author

@hoetmaaiers hoetmaaiers Feb 16, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A comment can be added saying it is autogenerated / only for theme development.

@@ -0,0 +1,123 @@
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose this is something autogenerated that we don't need to look at?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct. This is autogenerated. Or in more frontend terminology, transpiled from modern javascript (which is wat we want to write) into javascript every browser is able to understand, even the older ones.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it is transpiled every time that the theme builds, then should we avoid committing it to the git repository? Or is it still best-practice to commit it?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(same w/ the yarn.lock file...I'm happy to follow the guidance of others on this, since I'm not a JS dev, but just wanna flag it for discussion)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this theme.js, I think the big advantage of having it commited into the repo, is that you can still do pip install from the repo (as everybody is now doing, since there isn't an official release yet) and have a working theme without needing to transpile it yourself (and thus install the js toolchain).

This seems an important use case to keep working.

For yarn.lock, less sure.

We might want to add some check (on CI, or a pre-commit hook, ..) to ensure the transpiling was run? (or in the future)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should indeed be committed.

@@ -0,0 +1,31 @@
const path = require('path');
const merge = require('webpack-merge');
const exec = require('child_process').exec;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you had this from readthedocs, right? Maybe a short comment giving attribution would be good then

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My basis where I started from is indeed from readthedocs, the webpack.common file did change so much only basic boilerplate remains.

Giving attribution is a good idea. Maybe we should do this in the theme dev documentation?

@jorisvandenbossche
Copy link
Member

@hoetmaaiers some questions that might be related to this:

  • Should we look at including the (minified) bootstrap css/js in pandas_sphinx_theme/static/ as well using yarn/webpack, instead of loading it from their CDN?
  • It would be interesting that people using the theme could override a few key elements (like the primary color). I suppose that is something that sass variables could help with? But that means that the when setting such a variable in a project using this theme, they also need to use sass? Or can you use css variables for this without the need to recompile?
    (this might rather be for a different issue to discuss)

I think my main concern is not so much the difficulty in using it for developing on this theme (I could set it up quickly), but rather in the needed maintenance of the webpack scripts (although they are not that long)

@choldgraf
Copy link
Collaborator

Just a quick note on this, I think it is worth noting what benefits we can only get with webpack in order to weight the "pros" against the cons.

For example, I agree wholeheartedly that writing SCSS is cleaner and easier to read/maintain than writing CSS. However, I've actually found this to be fairly straightforward when using the Python libsass package. This will compile SCSS and you can write it to a static file locally as a part of the Sphinx build.

If SCSS is the main thing we get w/ webpack, then I am also happy to just write a little Sphinx extension that auto-runs libsass-python and generates a "regular" CSS file. But maybe there are other major benefits we get as well?

@hoetmaaiers hoetmaaiers force-pushed the feature/assets-webpack branch from 0922113 to 5afc0d2 Compare February 16, 2020 10:04
This fixes the yarn build:production script
@hoetmaaiers
Copy link
Collaborator Author

hoetmaaiers commented Feb 16, 2020

@hoetmaaiers some questions that might be related to this:

  • Should we look at including the (minified) bootstrap css/js in pandas_sphinx_theme/static/ as well using yarn/webpack, instead of loading it from their CDN?

Good idea to indeed include the bootstrap css/js not from a CDN. We could install them as an rpm package. This way yarn instapl handles the installation of all dependency packages.

  • It would be interesting that people using the theme could override a few key elements (like the primary color). I suppose that is something that sass variables could help with? But that means that the when setting such a variable in a project using this theme, they also need to use sass? Or can you use css variables for this without the need to recompile?
    (this might rather be for a different issue to discuss)

Allowing people to override a few key elements is indeed important for the theme to succeed. This can be done in different ways:

I think my main concern is not so much the difficulty in using it for developing on this theme (I could set it up quickly), but rather in the needed maintenance of the webpack scripts (although they are not that long)

Fair concern about the maintenance cost of Webpack, but the scripts are relatively simple and will not require to much maintenance without adding extra bundling steps. Also webpack is moreless a standard which helps in understanding and supporting it.

Just a quick note on this, I think it is worth noting what benefits we can only get with webpack in order to weight the "pros" against the cons.

For example, I agree wholeheartedly that writing SCSS is cleaner and easier to read/maintain than writing CSS. However, I've actually found this to be fairly straightforward when using the Python libsass package. This will compile SCSS and you can write it to a static file locally as a part of the Sphinx build.

If SCSS is the main thing we get w/ webpack, then I am also happy to just write a little Sphinx extension that auto-runs libsass-python and generates a "regular" CSS file. But maybe there are other major benefits we get as well?

Good idea to make the comparison, libsass-python is also interesting.
I try to list some pros/cons for both approaches:

Webpack Pros

  • Bundling of scss, modern javascript and other assets into a free to define output format.
  • Autoprefix css output to ensure all browsers are covered: https://github.com/postcss/autoprefixer
  • Minify css to reduce file size
  • With webpack comes the nom ecosystem. We can easily install some decencies this way: bootstrap, normalize.css, ...
  • Autoreload assets + documentation on save any change in the css, javascript or even .rst and .py files in development. This makes developing the theme way more trivial.

Webpack Cons

  • More dificultt to install for python developers. Conda assists in this, but the package.json & yarn lock files are pretty unknown I assume?
  • Needs some configuration in the webpack.config.js files to make it work. Changing it, requires understanding it.

I think the libsass-python solution is quite the opposite regarding pros & cons. It is limited to compiling scss to css; nothing more, nothing less.

For me webpack is in favor because of the easier development thanks to live reload on change.

@jorisvandenbossche
Copy link
Member

Allowing people to override a few key elements is indeed important for the theme to succeed. This can be done in different ways:

Regarding sass variables vs css variables: although bootstrap uses sass, it seems they also have some things as css variables in its compiled css, so you can still use that as well: https://getbootstrap.com/docs/4.4/getting-started/theming/#css-variables (I didn't in detail, but that might be a way to use sass in this repo, but still allow overriding eg just the primary color with css variable in projects using this theme)


For the webpack pros/cons: I think making use of packages that help with cross-browser / cross-platform compatibility can also be useful, so we need to think less about that when writing css.
And the live-editing-reload seems to be handy as well, the productivity of web developers is also important :)

Using a bunch of external packages for this of course also creates complexity, certainly if you are not familiar with the javascript ecosystem (e.g. I suppose that we will need to update versions in package.json from time to time? Are there tools that can help with this?)

I was thinking that we could also have a "pure python fallback" development mode, that would use libsass-python to compile the css and copy the js file into the correct place, in the make html step, so you could still use the default sphinx-way as well. But I assume that once you start to use some of the other pro's of using webpack (eg autoprefix), that won't be a realistic idea.

@jorisvandenbossche
Copy link
Member

@choldgraf @stijnvanhoey any further thought on this?
We can maybe start with only using the live reload + scss abilities (which is what I think this PR is doing?) that webpack provide, so it is still easy to go back if it turns out to be a hurdle?

@jorisvandenbossche
Copy link
Member

In readthedocs, it seems they also integrated webpack into setup.py: https://github.com/readthedocs/sphinx_rtd_theme/blob/master/setup.py

/* border-left: 5px solid rgb(238, 238, 238) !important; */
}

table.field-list th.field-name {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in a future PR I guess some of these could be re-written to leverage the SCSS, yeah?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Absolutely. In a different branch / future PR I am working on refactoring the different css files into a structured scss setup.

@choldgraf
Copy link
Collaborator

choldgraf commented Feb 20, 2020

I made a few questions/comments, but I think we could give it a shot and see how it feels for a few months. Then revisit after some time to decide if it truly improves the dev experience, or if users report some problems in their use of the theme related to these changes 👍

@stijnvanhoey
Copy link
Contributor

The choice for webpack is fine for me, I do think for this kind of project (focus on front-end theme development) the benefits of the webpack approach are there. Still, we should make sure to add some minimal documentation on how to setup this locally and make sure people are not providing PRs with edited css files...

I was thinking that we could also have a "pure python fallback" development mode, that would use libsass-python to compile the css and copy the js file into the correct place, in the make html step, so you could still use the default sphinx-way as well.

Actually I would try to document/describe 1 way to setup everything instead of multiple alternatives, either written ourselve or maybe @hoetmaaiers can refer to a good/stable setup documentation?

@choldgraf
Copy link
Collaborator

@stijnvanhoey I agree that we should try sticking with "one obvious way of doing things" and try to make up the difference with clear documentation. If over time that one obvious way is really cumbersome then we can discuss changing it

@hoetmaaiers
Copy link
Collaborator Author

I will provide a documentation part which goes into theme development. Setup, how to edit the theme, ... Is this something I add to this PR or can it be done in a later PR?

@jorisvandenbossche
Copy link
Member

Either way is fine for me. I can imagine it makes your other branches easier to manage if this one gets merged sooner rather than later?

@hoetmaaiers
Copy link
Collaborator Author

Indeed, I did my other styling working based on this Webpack setup, just for the added convenience of Webpack watching and compiling. Documentation is important, so if we can merge this branch first, I can immediately focus on providing the documentation first as a follow up branch.

@jorisvandenbossche
Copy link
Member

Let's do it that way then!

@jorisvandenbossche jorisvandenbossche merged commit 6b0192b into pydata:master Feb 25, 2020
@jorisvandenbossche
Copy link
Member

Thanks @hoetmaaiers ! Let's see how this goes ;)

@hoetmaaiers hoetmaaiers deleted the feature/assets-webpack branch February 25, 2020 10:59
This was referenced Feb 25, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants