lektor-website/docs/guides/webpack/index.html

391 lines
22 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="../../../static/styles.css?h=dff0aaad">
<link rel="stylesheet" href="../../../static/pygments.css">
<link rel="shortcut icon" href="../../../static/favicon.png?h=fa09bedd">
<title>Webpack | Documentation | Lektor Static Content Management System</title>
</head>
<body class="default">
<nav class="navbar navbar-inverse navbar-static-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed"
data-toggle="collapse" data-target="#navbar"
aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="../../../">Lektor</a>
</div>
<div id="navbar" class="collapse navbar-collapse">
<ul class="nav navbar-nav">
<li><a href="../../../downloads/">Download</a></li>
<li class="active"><a href="../../">Documentation</a></li>
<li><a href="../../../showcase/">Showcase</a></li>
<li><a href="../../../plugins/">Plugins</a></li>
<li><a href="../../../community/">Community</a></li>
<li><a href="../../../blog/">Blog</a></li>
</ul>
</div>
</div>
</nav>
<div class="body-wrapper">
<div class="container">
<div class="row">
<div class="col-sm-3">
<ul class="tree-nav nocontent">
<li><a href="../../">Welcome</a></li>
<li><a href="../../what/">What is Lektor</a>
<li><a href="../../installation/">Installation</a>
<li><a href="../../quickstart/">Quickstart</a>
<li><a href="../../project/">Project</a>
<li><a href="../../content/">Content</a>
<li><a href="../../templates/">Templates</a>
<li><a href="../../themes/">Themes</a>
<li><a href="../">Guides</a>
<ul>
<li><a href="../blog/">Blog</a>
<li><a href="../categories/">Categories</a>
<li><a href="../disqus/">Disqus Comments</a>
<li><a href="../error-pages/">Error Pages</a>
<li><a href="../page-order/">Page Order</a>
<li><a href="../pagination/">Pagination</a>
<li><a href="../portfolio/">Portfolio Sites</a>
<li><a href="../redirects/">Redirects</a>
<li><a href="../single-page/">Single-Page</a>
<li><a href="../sitemap/">Sitemap</a>
<li class="active"><a href="./">Webpack</a>
<ul></ul>
</ul>
<li><a href="../../deployment/">Deployment</a>
<li><a href="../../plugins/">Plugins</a>
<li><a href="../../models/">Data Modelling</a>
<li><a href="../../cli/">Command Line</a>
<li><a href="../../api/">API</a>
<li><a href="../../search/">Search</a>
</ul>
<div class="visible-md-block visible-lg-block">
<h4>This Page</h4>
<ul class="toc">
<li><a href="#enabling-the-plugin">Enabling the Plugin</a></li>
<li><a href="#webpack-setup">Webpack Setup</a><ul>
<li><a href="#package.json`"><code>package.json</code></a></li>
<li><a href="#webpack-config.js`"><code>webpack.config.js</code></a></li>
</ul></li>
<li><a href="#creating-the-app">Creating the App</a></li>
<li><a href="#running-the-server">Running the Server</a></li>
<li><a href="#manual-builds">Manual Builds</a></li>
<li><a href="#including-the-files">Including The Files</a></li>
</ul>
</div>
</div>
<div class="col-sm-9 doc-styling">
<h1>Webpack</h1>
<ul class=page-meta>
</ul>
<p>Websites are exploding in complexity and even static websites are no exception
to this. In particular systems like bootstrap and friends no longer just come
in CSS files but they come with their own build setup to ship JavaScript files,
they use Less or Sass to build the stylesheets and much more.</p>
<p>Right now there is a fight between different systems to figure out which way
the journey will go, but one of the best solutions has turned out to be
<a href="https://webpack.github.io/" class="ext">webpack</a>.</p>
<p>Webpack is not natively supported by Lektor but there is an official <a href="https://github.com/lektor/lektor-webpack-support" class="ext">Webpack
Support Plugin</a> which
can be used to make Lektor and Webpack friends.</p>
<h2 id="enabling-the-plugin">Enabling the Plugin</h2><p>First you need to enable the plugin. The following command will do that
for you:</p>
<pre><code>$ lektor plugins add webpack-support
</code></pre>
<h2 id="webpack-setup">Webpack Setup</h2><p>Now you need to configure webpack. The plugin expects a webpack project in the
<code>webpack/</code> folder. Within you will need a <code>package.json</code> as well as a
<code>webpack.config.js</code></p>
<h3 id="package.json`"><code>package.json</code></h3><p>This file instructs <code>npm</code> which packages we will need.</p>
<p><a href="https://docs.npmjs.com/cli/init" class="ext">npm-init</a> is a command-line tool to
interactively create a <code>package.json</code> file.</p>
<pre><code>$ npm init
</code></pre>
<p>This will ask you a bunch of questions (invoke with <code>--yes</code> to use default
values) and then generate a <code>package.json</code> file for you.</p>
<p>It should look similar to the following example. Please <strong>do not</strong> just
copy-paste this! Instead run the tool, so that your <code>package.json</code> meets
the latest format specification.</p>
<div class="hll"><pre><span></span><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;name&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;lektor-example&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;version&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;0.1.0&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;description&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;main&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;index.js&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;scripts&quot;</span><span class="p">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nt">&quot;test&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;echo \&quot;Error: no test specified\&quot; &amp;&amp; exit 1&quot;</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nt">&quot;author&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;&quot;</span><span class="p">,</span>
<span class="w"> </span><span class="nt">&quot;license&quot;</span><span class="p">:</span><span class="w"> </span><span class="s2">&quot;MIT&quot;</span>
<span class="p">}</span>
</pre></div>
<p>Now we can <code>npm install</code> all the things we want:</p>
<pre><code>$ npm install --save-dev webpack babel-core node-sass babel-loader sass-loader css-loader url-loader style-loader file-loader extract-text-webpack-plugin
</code></pre>
<p>This will install webpack itself together with babel and sass as well as
a bunch of loaders we need for getting all that configured. Because we
created a <code>package.json</code> before and we used <code>--save-dev</code> the dependencies
will be remembered in the <code>package.json</code> file.</p>
<h3 id="webpack-config.js`"><code>webpack.config.js</code></h3><p>Next up is the webpack config file. Here we will go with a very basic
setup that's good enough to cover most things you will encounter. The
idea is to build the files from <code>webpack/scss</code> and <code>webpack/js</code> into
<code>assets/static/gen</code> so that we can use it even if we do not have webpack
installed for as long as someone else ran it before.</p>
<p>In this example we will configure the following things:</p>
<ul>
<li>all <code>.scss</code> files will be processed with Sass</li>
<li>all <code>.js</code> files will be processed with Babel to convert ES6 into ES5</li>
<li>JS and CSS files will be minified</li>
<li>all built files will go to <code>assets/static/gen</code></li>
<li>there will be a <code>gen/app.js</code> and a <code>gen/styles.css</code> file to include</li>
</ul>
<div class="hll"><pre><span></span><span class="kd">var</span><span class="w"> </span><span class="nx">webpack</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">require</span><span class="p">(</span><span class="s1">&#39;webpack&#39;</span><span class="p">);</span>
<span class="kd">var</span><span class="w"> </span><span class="nx">path</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">require</span><span class="p">(</span><span class="s1">&#39;path&#39;</span><span class="p">);</span>
<span class="kd">var</span><span class="w"> </span><span class="nx">ExtractTextPlugin</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nx">require</span><span class="p">(</span><span class="s1">&#39;extract-text-webpack-plugin&#39;</span><span class="p">);</span>
<span class="nx">module</span><span class="p">.</span><span class="nx">exports</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">entry</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="s1">&#39;app&#39;</span><span class="o">:</span><span class="w"> </span><span class="s1">&#39;./js/main.js&#39;</span><span class="p">,</span>
<span class="w"> </span><span class="s1">&#39;styles&#39;</span><span class="o">:</span><span class="w"> </span><span class="s1">&#39;./scss/main.scss&#39;</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nx">output</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">path</span><span class="o">:</span><span class="w"> </span><span class="nx">path</span><span class="p">.</span><span class="nx">dirname</span><span class="p">(</span><span class="nx">__dirname</span><span class="p">)</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s1">&#39;/assets/static/gen&#39;</span><span class="p">,</span>
<span class="w"> </span><span class="nx">filename</span><span class="o">:</span><span class="w"> </span><span class="s1">&#39;[name].js&#39;</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nx">devtool</span><span class="o">:</span><span class="w"> </span><span class="s1">&#39;#cheap-module-source-map&#39;</span><span class="p">,</span>
<span class="w"> </span><span class="nx">resolve</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">modules</span><span class="o">:</span><span class="w"> </span><span class="p">[</span><span class="s1">&#39;node_modules&#39;</span><span class="p">],</span>
<span class="w"> </span><span class="nx">extensions</span><span class="o">:</span><span class="w"> </span><span class="p">[</span><span class="s1">&#39;.js&#39;</span><span class="p">]</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nx">module</span><span class="o">:</span><span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="nx">rules</span><span class="o">:</span><span class="w"> </span><span class="p">[</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">test</span><span class="o">:</span><span class="w"> </span><span class="sr">/\.js$/</span><span class="p">,</span><span class="w"> </span><span class="nx">exclude</span><span class="o">:</span><span class="w"> </span><span class="sr">/node_modules/</span><span class="p">,</span>
<span class="w"> </span><span class="nx">loader</span><span class="o">:</span><span class="w"> </span><span class="s1">&#39;babel-loader&#39;</span><span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">test</span><span class="o">:</span><span class="w"> </span><span class="sr">/\.scss$/</span><span class="p">,</span>
<span class="w"> </span><span class="nx">loader</span><span class="o">:</span><span class="w"> </span><span class="nx">ExtractTextPlugin</span><span class="p">.</span><span class="nx">extract</span><span class="p">({</span>
<span class="w"> </span><span class="nx">fallback</span><span class="o">:</span><span class="w"> </span><span class="s1">&#39;style-loader&#39;</span><span class="p">,</span>
<span class="w"> </span><span class="nx">use</span><span class="o">:</span><span class="w"> </span><span class="s1">&#39;css-loader!sass-loader&#39;</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">)</span><span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">test</span><span class="o">:</span><span class="w"> </span><span class="sr">/\.css$/</span><span class="p">,</span>
<span class="w"> </span><span class="nx">loader</span><span class="o">:</span><span class="w"> </span><span class="nx">ExtractTextPlugin</span><span class="p">.</span><span class="nx">extract</span><span class="p">({</span>
<span class="w"> </span><span class="nx">fallback</span><span class="o">:</span><span class="w"> </span><span class="s1">&#39;style-loader&#39;</span><span class="p">,</span>
<span class="w"> </span><span class="nx">use</span><span class="o">:</span><span class="w"> </span><span class="s1">&#39;css-loader&#39;</span><span class="w"> </span><span class="p">}</span><span class="w"> </span><span class="p">)</span><span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="nx">test</span><span class="o">:</span><span class="w"> </span><span class="sr">/\.(woff2?|ttf|eot|svg|png|jpe?g|gif)$/</span><span class="p">,</span>
<span class="w"> </span><span class="nx">loader</span><span class="o">:</span><span class="w"> </span><span class="s1">&#39;file&#39;</span><span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="p">]</span>
<span class="w"> </span><span class="p">},</span>
<span class="w"> </span><span class="nx">plugins</span><span class="o">:</span><span class="w"> </span><span class="p">[</span>
<span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">ExtractTextPlugin</span><span class="p">({</span>
<span class="w"> </span><span class="nx">filename</span><span class="o">:</span><span class="w"> </span><span class="s1">&#39;styles.css&#39;</span><span class="p">,</span>
<span class="w"> </span><span class="nx">allChunks</span><span class="o">:</span><span class="w"> </span><span class="kc">true</span>
<span class="w"> </span><span class="p">}),</span>
<span class="w"> </span><span class="ow">new</span><span class="w"> </span><span class="nx">webpack</span><span class="p">.</span><span class="nx">optimize</span><span class="p">.</span><span class="nx">UglifyJsPlugin</span><span class="p">()</span>
<span class="w"> </span><span class="p">]</span>
<span class="p">};</span>
</pre></div>
<h2 id="creating-the-app">Creating the App</h2><p>Now we can start building our app. We configured at least two files
in webpack: <code>js/main.js</code> and <code>scss/main.scss</code>. Those are the entry
points we need to have. You can create them as empty files in
<code>webpack/js/main.js</code> and <code>webpack/scss/main.scss</code>.</p>
<h2 id="running-the-server">Running the Server</h2><p>Now you're ready to go. When you run <code>lektor server</code> webpack will not
run, instead you need to now run it with the <code>webpack</code> flag which
will enable the webpack build:</p>
<pre><code>$ lektor server -f webpack
</code></pre>
<p>Webpack automatically builds your files into <code>assets/static/gen</code> and this is
where Lektor will then pick up the files. This is done so that you can ship
the webpack generated assets to others that do not have webpack installed which
simplifies using a Lektor website that uses webpack.</p>
<h2 id="manual-builds">Manual Builds</h2><p>To manually trigger a build that also invokes webpack you can also pass
the <code>webpack</code> flag there:</p>
<pre><code>$ lektor build -f webpack
</code></pre>
<h2 id="including-the-files">Including The Files</h2><p>Now you need to include the files in your template. This will do it:</p>
<div class="hll"><pre><span></span><span class="p">&lt;</span><span class="nt">link</span> <span class="na">rel</span><span class="o">=</span><span class="s">&quot;stylesheet&quot;</span> <span class="na">href</span><span class="o">=</span><span class="s">&quot;</span><span class="cp">{{</span>
<span class="s1">&#39;/static/gen/styles.css&#39;</span><span class="o">|</span><span class="nf">asseturl</span> <span class="cp">}}</span><span class="s">&quot;</span><span class="p">&gt;</span>
<span class="p">&lt;</span><span class="nt">script</span> <span class="na">type</span><span class="o">=</span><span class="s">text/javascript</span> <span class="na">src</span><span class="o">=</span><span class="s">&quot;</span><span class="cp">{{</span>
<span class="s1">&#39;/static/gen/app.js&#39;</span><span class="o">|</span><span class="nf">asseturl</span> <span class="cp">}}</span><span class="s">&quot;</span> <span class="na">charset</span><span class="o">=</span><span class="s">&quot;utf-8&quot;</span><span class="p">&gt;&lt;/</span><span class="nt">script</span><span class="p">&gt;</span>
</pre></div>
<div class="comment-box">
<h2>Comments</h2>
<div id="disqus_thread"></div>
<script>
var disqus_config = function() { this.page.identifier = "/docs/guides/webpack"; this.page.url = "https://www.getlektor.com/docs/guides/webpack/"; };
(function() {
var d = document, s = d.createElement('script');
s.src = '//lektordocumentation.disqus.com/embed.js';
s.setAttribute('data-timestamp', +new Date());
(d.head || d.body).appendChild(s);
})();
</script>
<noscript>
Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript"
rel="nofollow">comments powered by Disqus.</a>
</noscript>
</div>
</div>
</div>
</div>
</div>
<div class="bottomsummary">
<div class="container">
</div>
</div>
<footer>
<div class="container">
<div class="row">
<div class="col-sm-4 icon-bar">
<a href="https://github.com/lektor/lektor/" title="Lektor on GitHub"
><i class="fa fa-github"></i></a>
<a href="https://github.com/lektor/lektor/issues/" title="Report Issues for Lektor"
><i class="fa fa-bug"></i></a>
<a href="https://twitter.com/getlektor" title="Find Lektor on Twitter"
><i class="fa fa-twitter"></i></a>
<a href="https://gitter.im/lektor/lektor" title="Chat on Gitter"
><i class="fa fa-comment"></i></a>
<a href="https://github.com/lektor/lektor-website/tree/master/content/docs/guides/webpack/contents.lr" title="View source for this page"><i class="fa fa-code"></i></a>
</div>
<div class="col-sm-8">
<a href="../../../license/">License & Copyright</a>
<a href="../../../contact/">Contact</a>
Made with <i class="fa fa-fw fa-heart" title="Heart"><span hidden>Heart</span></i> in Carinthia
</div>
</div>
</div>
</footer>
<script type=text/javascript src="../../../static/app.js?h=396519c0" charset="utf-8"></script>
<script>
((window.gitter = {}).chat = {}).options = {
room: 'lektor/lektor',
activationElement: null
};
document.write('<button class="js-gitter-toggle-chat-button">Toggle Chat</button>');
var dnt = navigator.doNotTrack || window.doNotTrack || navigator.msDoNotTrack;
if (dnt != "1" && dnt != "yes") {
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
ga('create', 'UA-70822533-1', 'auto');
ga('set', 'anonymizeIp', true);
ga('send', 'pageview');
} else {
console.debug("Respecting Do-Not-Track, not running analytics.");
}
</script>
<script async src='https://www.google-analytics.com/analytics.js'></script>
<script async defer id="github-bjs" src="https://buttons.github.io/buttons.js"></script>
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');</script>
<script src="https://sidecar.gitter.im/dist/sidecar.v1.js" async defer></script>
</body>
</html>