rstudio / blogdown

Create Blogs and Websites with R Markdown
https://pkgs.rstudio.com/blogdown/
1.74k stars 330 forks source link

Use each blog post's renv environment when rendering #469

Open solarchemist opened 4 years ago

solarchemist commented 4 years ago

Right now (and please correct me if I'm wrong) blogdown uses the global R environment when it's rendering each blog post.

Would it be possible to make blogdown use each blog post's local R environment (specifically renv) instead?

I am suggesting something along these lines:

This way, I think blogdown would achieve several benefits. In particular, re-running blogdown would be less prone to break stuff (making blogdown behave a little more like distill in that regard, effectively inoculating each blog post against changing package versions). But it would also make it much easier to have only certain blog posts use specific package versions without having to muddle the global R installation.

What follows are the steps I took to test if blogdown uses renv's environment if a blog post specifies one (please correct me if I'm missing something).

As a simple test, I have created a new blog post for my existing blog using RStudio 1.3 (by creating a new project, and checking "use renv"). Then I created a plot that uses ggrepel's segment.curvature functionality (which is available in the latest dev version, but gives a warning message "unknown parameter" in the CRAN version).

So inside the project/blog post (which uses renv):

> renv::install("slowkow/ggrepel")
> packageVersion("ggrepel")
[1] ‘0.9.0’

and compiling the blog post using RStudio yields the expected curved ggrepel segments and no warning messages.

But when re-compiling the site with blogdown, the warning message is seen in the CLI output, and the resulting plot uses straight segments instead of nicely curved ones. And I can easily confirm that my global R environment uses the CRAN version of ggrepel:

> packageVersion("ggrepel")
[1] ‘0.8.2’

To re-iterate my point: would it be possible to make blogdown support renv for each blog post?


By filing an issue to this repo, I promise that

yihui commented 4 years ago

That sounds like a great suggestion! We'll definitely consider it in the future. Thank you!

cderv commented 3 years ago

Hi @solarchemist

We've been working hard on a new blogdown version and we will make release of 1.0 soon. https://community.rstudio.com/t/blogdown-v1-0-to-be-released-soon/92604

Part of the change we made and features we had may help in your usage:

By any chance, have you tried the new version yet ? If not, can you give it a spin (on a demo site maybe) to see if it changes thing for you ?

It will not be the same as having a "project" library for each of your Rmd post but old post won't be rendered anymore so new packages for new posts won't alter the results of previous posts as it could before in some cases.

About a library per post, this could lead to an heavy blog with all the duplicated libraries. However, with renv cache mechanism and renv lockfile I could see the advantage of having a lockfile per post that you could use to rerendered a post. maybe by recreating the library temporarily for the post rendering 🤔

Anyway, eager to here how the new stuff could change (or not) your existing workflow and your need of renv project for each blog post. Thanks!

solarchemist commented 3 years ago

Thanks for your kind words @cderv

It took me a while to get around to it, but I have finally upgraded R (v4.0), blogdown (v1.1) and now my blog. And I must say the changes to blogdown makes blogging with it significantly easier. Nice work!

Not building Rmd posts by default works very well, and creates peace of mind compared to before, just like you indicated. Also, asset bundling is awesome! It took a little work to edit image paths and whatnot in my existing blog posts, but bundling assets inside each blog post directory is clearly the better approach.

I think that thanks to asset bundling, now more than ever, each blog post becomes its own little stand-alone project. As such, it becomes even more rational to have each blog post be its own renv project, and it would be just awesome if blogdown actually used such renv environments when rendering.

As to the risk for bloated renv directories, I think I can put you at ease. Like you said, with the renv cache mechanism (I have set RENV_PATHS_ROOT=/nice/central/location/renv in Renviron.site) the renv library in each blog post is simply a long list of symbolic links. And I don't think there is any need for blogdown to actually do anything overly complicated to use a blog post's renv.

In practical terms, I see two approaches: blogdown can either cd into each blog post directory before rendering it and thus automatically invoke renv (perhaps along the lines in my first comment), or else, blogdown can somehow load each blog post's ./.Rprofile file before rendering said blog post (which should achieve the same thing).

In any case, congratulations on a significantly improved v1.0+!

yihui commented 3 years ago

We had a meeting with Kevin (renv's author) today. He mentioned a few interesting methods related to using renv for individual Rmd documents: renv::activate(), renv::use(), and renv::embed(). If you want to learn more, perhaps @cderv can share more info.

alexpghayes commented 2 years ago

Are there any updates on this? I'm trying to revitalize an old blog post that relies on some archived packages and would love pointers on how to use renv on a per-qmd basis.

cderv commented 2 years ago

per-qmd basis.

Just to clarify, are you using Quarto and .qmd formats ? Or you meant Rmd files ?

alexpghayes commented 2 years ago

I'm starting to write blogposts in .qmd so ideally some sort of renv environment specific to a .qmd file would be great, but if something only works for .Rmd files that's also fine.

cderv commented 2 years ago

I am asking because Quarto has a freeze feature useful for that purpose of having old post stay the same (https://quarto.org/docs/computations/r.html#freezing-execution, https://quarto.org/docs/projects/code-execution.html#freeze).

Also, since blogdown v1, post are not rerendered by default. Which prevent so difficulties to manage blog with old post.

However, if you want to rerun some R code from old blog post, then renv should be indeed quite useful. We are thinking that the recent feature renv::use() would help : https://rstudio.github.io/renv/articles/use.html renv::embed() (https://rstudio.github.io/renv/reference/embed.html) will be more helpful with R Markdown file, as it should be able to include a lockfile into a chunk directly. We were not sure that a specific blogdown support for this is needed. Our understanding is that when the rendering happens, the specific package definition in renv::use() would take care of using the correct packages. That is yet to be tried in a real use case 😅 Did you already look into this in the past ?

solarchemist commented 1 month ago

There's a recent blog post with an example of using renv::use() (as @cderv already noted) for a Quarto blog that could probably be applied to blogdown too (not tested myself yet, I just thought that this issue could be a good place to put this reminder to myself). Discussed in toots by the blog post's author: 1, 2.