<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Drupal - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Drupal - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sun, 24 May 2026 22:25:33 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/drupal/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ The best way to manage your Drupal workflow ]]>
                </title>
                <description>
                    <![CDATA[ By Ankit Jain One of the struggles that developers face when moving to Drupal 8 is the lack of best practices in deploying Drupal sites. The Challenges in deployment revolve around Dependency Management, Drupal Contrib Modules/Themes, Configuration M... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/the-best-way-to-manage-your-drupal-workflow-ade9525a84c0/</link>
                <guid isPermaLink="false">66d45d98a44b8bb91150f649</guid>
                
                    <category>
                        <![CDATA[ Drupal ]]>
                    </category>
                
                    <category>
                        <![CDATA[ PHP ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Fri, 27 Apr 2018 23:54:06 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*yhQ2g4zBCCDEo-mGalYocg.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Ankit Jain</p>
<p>One of the struggles that developers face when moving to Drupal 8 is the lack of best practices in deploying Drupal sites. The Challenges in deployment revolve around Dependency Management, Drupal Contrib Modules/Themes, Configuration Management, and of course Code Base.</p>
<p>Drupal 7 has no such problems. But ahhh, Drupal 8 comes with lots of stuff to manage. One of the biggest changes in Drupal 8 is the adoption of Composer. Good things come at a price.</p>
<p>We will use one codebase for one Drupal site and use Git for version control and deployment.</p>
<h3 id="heading-composer">Composer</h3>
<p><a target="_blank" href="https://getcomposer.org/">Composer</a> is a dependency manager for PHP (like npm for Node or pip for Python). Drupal core uses Composer to manage core dependencies like Symfony components and Guzzle. Composer allows us to systematically manage a list of dependencies and their subsidiary dependencies. Composer installs these dependencies via a manifest file called composer.json.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/pUUUDONIPBc5YhXinYyVuLMZ6Gw8pfcjLaga" alt="Image" width="474" height="350" loading="lazy"></p>
<p>This composer.json file contains the dependencies that the project requires. You can install it by running</p>
<pre><code>composer install
</code></pre><p>for the first time. It locates, downloads, validates, and loads the packages. It also ensures that exactly the right versions for each package are used, and maintains the log file called composer.lock.</p>
<p><strong>Note: always commit your composer.lock file,</strong> because it contains the exact version of the dependencies that you have defined in the project.</p>
<p>If you want to update any specific package, it’s a good practice to run this command:</p>
<pre><code>composer update package/package-name
</code></pre><p>You should never run <strong>composer update,</strong> because composer will try to update every single dependency. This can cause problems to your site.</p>
<h3 id="heading-drupal-composer">Drupal Composer</h3>
<p><a target="_blank" href="https://github.com/drupal-composer/drupal-project">drupal-composer/drupal-project</a> is the life-saver project for managing your site dependencies with Composer.</p>
<p>To install this project template, run this command:</p>
<pre><code>composer create-project drupal-composer/drupal-project:<span class="hljs-number">8.</span>x-dev drupal8 — stability dev — no-interaction
</code></pre><p>It will automatically install a Drupal site with all the dependencies. It will also install <a target="_blank" href="https://drupalconsole.com/">Drupal console</a> and <a target="_blank" href="https://github.com/drush-ops/drush">Drush</a> locally.</p>
<p>Composer is one of the fastest ways to install dependencies, as it caches the dependencies and loads data from the cache the next time.</p>
<h4 id="heading-directory-structure"><strong>Directory structure</strong></h4>
<p><img src="https://cdn-media-1.freecodecamp.org/images/s7H0wBMBgz4kfLm1hjGlxdNLJV5KwlBsb9EN" alt="Image" width="480" height="271" loading="lazy"></p>
<p>It is different from the Drupal directory structure. You can reassemble web directory with the public directory which contains Drupal files. All third party dependencies are outside the web folder.</p>
<p>You can install any Drupal Modules, themes, and profiles through composer which will be downloaded in the contrib folder inside the modules, themes, and profiles, respectively. In this way, the composer.lock file will have a record of all the Drupal contrib modules along with the third party dependencies.</p>
<p>To download any modules and themes using composer, run the following:</p>
<pre><code>composer <span class="hljs-built_in">require</span> drupal/mediumish_blog
</code></pre><pre><code># For installing theme, we will use drupal <span class="hljs-built_in">console</span>
</code></pre><pre><code>drupal theme:install mediumish_blog
</code></pre><h4 id="heading-gitignore"><strong>Gitignore</strong></h4>
<p>As are all the dependencies and Drupal contrib modules, themes are managed by composer. Therefore, we will not push this content to Git.</p>
<pre><code># Ignore directories generated by Composer /drush/contrib /vendor/ <span class="hljs-regexp">/web/</span>core/ <span class="hljs-regexp">/web/m</span>odules/contrib/ <span class="hljs-regexp">/web/</span>themes/contrib/ <span class="hljs-regexp">/web/</span>profiles/contrib/ <span class="hljs-regexp">/web/</span>libraries/
</code></pre><pre><code># Ignore sensitive information /web/sites<span class="hljs-comment">/*/settings.php /web/sites/*/</span>settings.local.ph
</code></pre><h3 id="heading-configuration-management">Configuration management</h3>
<p>Deployment and configuration management are common actions of a project life cycle. We have installed various modules and configured our local site, but our production site has no such configuration.</p>
<p>In Drupal 7, we had the features module, which is used to sync configuration. But Drupal 8 has an inbuilt solution for managing configurations. This allows you to export complete website configurations and store them in YAML files. Exported files can be imported to another website with the same result.</p>
<p>Drupal’s configuration system helps to solve the config files synchronization problem in two ways: a unified way to store configuration, and a process to import/export changes between instances of the same site.</p>
<h4 id="heading-how-to-synchronize-config-files"><strong>How to synchronize config files</strong></h4>
<p>Open /web/sites/default/settings.php and set $config_directories[‘sync’]</p>
<pre><code>$config_directories[‘sync’] = ‘../config/sync’;
</code></pre><p>It’s a good practice to store config files outside of the web directory to avoid making them accessible from the Internet.</p>
<p>Now use the Drupal console to export the configuration:</p>
<pre><code>drupal config:<span class="hljs-keyword">export</span>
</code></pre><pre><code># <span class="hljs-keyword">import</span> on prod server
</code></pre><pre><code>drupal config:<span class="hljs-keyword">import</span>
</code></pre><p><strong>Note:</strong> the production and local Drupal sites should have same UUIDs. Check <a target="_blank" href="https://www.drupal.org/docs/8/configuration-management/managing-your-sites-configuration">here</a> for more info.</p>
<p><strong>Note:</strong> Drupal configuration management has a bug — custom blocks data should neither be imported nor be exported. View the Issue Link <a target="_blank" href="https://www.drupal.org/project/drupal/issues/2756331">here</a>.</p>
<h3 id="heading-git">Git</h3>
<p>We will use Git to add, commit, and push the local site’s data with all the configuration. This will be pulled from the prod server/site. Let’s see the flow:</p>
<pre><code># Local
</code></pre><pre><code>git add .
</code></pre><pre><code>git commit -m”Add commit message”
</code></pre><pre><code>git push origin HEAD
</code></pre><pre><code># Server
</code></pre><pre><code>git pull otigin HEAD
</code></pre><pre><code>composer install # to install any <span class="hljs-keyword">new</span> dependencies, drupal contrib modules, themes
</code></pre><pre><code>drupal config:<span class="hljs-keyword">import</span> # to <span class="hljs-keyword">import</span> the configuration
</code></pre><pre><code>drupal cache:rebuild all # rebuild the cache
</code></pre><h4 id="heading-update-modules-themes-and-profiles"><strong>Update modules, themes, and profiles</strong></h4>
<pre><code>composer update drupal/mediumish_blog
</code></pre><pre><code>drupal update:execute mediumish_blog
</code></pre><pre><code>drupal update:execute all
</code></pre><h4 id="heading-update-drupal-core"><strong>Update Drupal core</strong></h4>
<p>Generally, we face problems in updating the Drupal core. But composer has a simple way to manage this, too:</p>
<pre><code>composer update drupal/core — <span class="hljs-keyword">with</span>-dependencies
</code></pre><p>It will update the Drupal core and all its associated dependencies.</p>
<h3 id="heading-managing-environment-configuration">Managing environment configuration</h3>
<p>My favorite aspect of Drupal, as a developer, is the ability to manage different environment configurations. This can be done by using the <a target="_blank" href="https://github.com/vlucas/phpdotenv">vlucas/phpdotenv</a> module, which also comes with the Drupal composer template.</p>
<p>Anything that is likely to change between deployment environments — such as database credentials or credentials for 3rd party services — should be extracted from the code into environment variables. Basically, an <code>.env</code> file is an easy way to load custom configuration variables that your application needs without having to modify any other files.</p>
<p>Rename .env.example to .env file and add all the credentials as a key-value pair in .env file.</p>
<p>load.environment.php file in the root will load this .env file and make it available for you.</p>
<h4 id="heading-how-to-use-env-file"><strong>How to use .env file</strong></h4>
<p>Open /web/sites/default/setting.php and add this set of code:</p>
<pre><code>$databases[‘<span class="hljs-keyword">default</span>’][‘<span class="hljs-keyword">default</span>’] = [ ‘database’ =&gt; getenv(‘MYSQL_DATABASE’), ‘driver’ =&gt; ‘mysql’, ‘host’ =&gt; getenv(‘MYSQL_HOSTNAME’), ‘namespace’ =&gt; ‘Drupal\\Core\\Database\\Driver\\mysql’, ‘password’ =&gt; getenv(‘MYSQL_PASSWORD’), ‘port’ =&gt; getenv(‘MYSQL_PORT’), ‘prefix’ =&gt; ‘’, ‘username’ =&gt; getenv(‘MYSQL_USER’), ];
</code></pre><p>Open .env file and set the following credentials:</p>
<pre><code>MYSQL_DATABASE=’db_name’ MYSQL_HOSTNAME=’localhost’ MYSQL_PASSWORD=’secret’ MYSQL_PORT=’<span class="hljs-number">3306</span><span class="hljs-string">' MYSQL_USER=’root’</span>
</code></pre><p>Now, as all our credentials are stored in the .env file, we can push our settings.php to the server and manage its configuration through .env file.</p>
<p>We generally enable twig debugging while in development and disable upon production. This can also be done easily and smoothly through an .env file.</p>
<p>Add a new key value pair in .env file:</p>
<pre><code>APP_ENV=’local’
</code></pre><p>Now copy web/sites/example.settings.local.php to web/sites/default/settings.local.php and add this code in web/sites/development.services.yml under parameters:</p>
<pre><code>twig.config: debug: <span class="hljs-literal">true</span> auto_reload: <span class="hljs-literal">true</span> cache: <span class="hljs-literal">false</span>
</code></pre><p>Now open web/sites/default/settings.php and add this code:</p>
<pre><code>$env = getenv(‘APP_ENV’);
</code></pre><pre><code>$base_path = $app_root . ‘/’ . $site_path; $settingsFile = $base_path . ‘/settings.’ . $env . ‘.php’;
</code></pre><pre><code><span class="hljs-keyword">if</span> (file_exists($settingsFile)) { include $settingsFile; }
</code></pre><p>So, in this way, if you set your APP_ENV=’local’, Twig debug will be enabled. Upon production, you can disable by setting APP_ENV=’prod’. You can also configure different configurations for different environments.</p>
<h3 id="heading-conclusion">Conclusion</h3>
<p>Drupal 8 offers a built-in solution for exporting and importing site configurations, which is way better than what you could do in D7. Dependencies and contrib modules/themes are managed by the composer itself.</p>
<p>It’s not yet perfect, as there is no standard approach, but the workflow described above is a simple and efficient solution. You can define your own workflow based on your needs.</p>
<p>For reference, I have pushed the code to <a target="_blank" href="https://github.com/ankitjain28may/drupal-best-practices">this repo</a>.</p>
<p>I hope you have found this article useful. I would love to hear your feedback :)</p>
<p>This article is from my own blog. To read more such articles, follow it <a target="_blank" href="http://ankitjain28.me/">here</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
