Vanilla CLI Build Transformations (Deprecated) - Vanilla Success
<main> <article class="userContent"> <p>The Vanilla CLI’s sass and javascript build processes provide multiple methods to import other sass/css or javascript files. <em>This only works with the built-in build processes.</em></p><h2 data-id="javascript">Javascript</h2><p>The javascript files are bundled <em>not concatenated</em>. Concatenation is how many legacy process work. A legacy build script would need to define the order that javascript files would get loaded in and they would get attached to each other in order. Each file would place their contents in the global namespace and rely on their particular order to only reference things loaded before themselves. Bundling allows import/require statements to be resolved dynamically, and be deduplicated. All dependancies must be implicitly defined at the top of each file.</p><p>The babel preset used will be <a href="https://github.com/vanilla/babel-preset" rel="nofollow noreferrer ugc">@vanilla/babel-preset</a>.</p><h3 data-id="syntax">Syntax</h3><p>All ES2017 syntax and features are supported, including</p><ul><li><code class="code codeInline" spellcheck="false" tabindex="0">class</code></li><li><code class="code codeInline" spellcheck="false" tabindex="0">Promise</code></li><li><code class="code codeInline" spellcheck="false" tabindex="0">async/await</code></li><li>Generator functions <code class="code codeInline" spellcheck="false" tabindex="0">function* name()</code></li><li><code class="code codeInline" spellcheck="false" tabindex="0">let</code>/<code class="code codeInline" spellcheck="false" tabindex="0">const</code></li><li>arrow functions <code class="code codeInline" spellcheck="false" tabindex="0">() => {}</code></li><li>template strings</li><li>Rest/Spread <code class="code codeInline" spellcheck="false" tabindex="0">...params</code></li><li>default function values</li><li>array & object destructuring</li><li>Iterators & <code class="code codeInline" spellcheck="false" tabindex="0">for..of</code></li><li><code class="code codeInline" spellcheck="false" tabindex="0">Symbol</code></li><li><code class="code codeInline" spellcheck="false" tabindex="0">Map</code>/<code class="code codeInline" spellcheck="false" tabindex="0">Set</code></li><li><code class="code codeInline" spellcheck="false" tabindex="0">Array.prototype.map</code>/<code class="code codeInline" spellcheck="false" tabindex="0">Array.prototype.reduce</code>/<code class="code codeInline" spellcheck="false" tabindex="0">Array.prototype.filter</code></li><li><code class="code codeInline" spellcheck="false" tabindex="0">import</code>/<code class="code codeInline" spellcheck="false" tabindex="0">export</code></li><li><code class="code codeInline" spellcheck="false" tabindex="0">JSX</code> support</li></ul><h3 data-id="methods-of-exporting-javascript">Methods of exporting javascript</h3><p>There are currently multiple different ways to export javascript and this tool supports all of them. <a href="https://hacks.mozilla.org/2015/08/es6-in-depth-modules/" rel="nofollow noreferrer ugc">ES Modules</a> are the preferred method though.</p><h4 data-id="es-module-export">ES Module Export</h4><p>ES modules provide 2 types of exports. Default and named exports. See <a href="https://hacks.mozilla.org/2015/08/es6-in-depth-modules/" rel="nofollow noreferrer ugc">ES Modules in depth</a> for more details.</p><pre class="code codeBlock" spellcheck="false" tabindex="0">export default function defaultFunction() { return "foo"; } export const myVariable = 'bar' </pre><h4 data-id="require.js-module.exports">require.js <code class="code codeInline" spellcheck="false" tabindex="0">module.exports</code></h4><p>Require.js is Node’s module system. A file exports whatever it’s module.exports. While ES modules can have both named exports and a default export, require.js module can have one or the other. Not both.</p><pre class="code codeBlock" spellcheck="false" tabindex="0">module.exports = { function1, function2, object1 } // or module.exports = function(){ } </pre><h3 data-id="methods-of-importing-javascript">Methods of importing javascript</h3><p>While browser implementations of ES Modules only support importing other ES Modules, this build tools leverages <a href="https://github.com/webpack/webpack" rel="nofollow noreferrer ugc">Webpack</a> to allow mixing import methods.</p><h4 data-id="es-module-imports">ES Module Imports</h4><p>You will almost always be able to use ES Module imports even if the module you are trying to import is using <code class="code codeInline" spellcheck="false" tabindex="0">require.js</code> (most npm modules will). If you need to import something dynamically that will require one of <a href="https://webpack.js.org/guides/code-splitting/" rel="nofollow noreferrer ugc">webpack’s dynamic imports</a>.</p><pre class="code codeBlock" spellcheck="false" tabindex="0">// Import a default export import Thing from 'thing'; // Import a named export import {VariableOrFunction} from 'thing'; // Import both import Thing, {VariableOrFunction1, VariableOrFunction2} from 'thing'; // Import everything into "namespace" type construct // If there is a default it will be assigned to the variable 'Thing.default' import * as Thing from 'thing'; // Import something that doesn't export any module // This is generally used for something that attatches globally or has // global side effects (e.g. some jquery plugins) import 'jquery-thing'; </pre><p><code class="code codeInline" spellcheck="false" tabindex="0">jquery</code> itself is already attatched globally by Vanilla, so you don’t need to worry about importing it. You can just access it as <code class="code codeInline" spellcheck="false" tabindex="0">jQuery</code> or <code class="code codeInline" spellcheck="false" tabindex="0">$</code>.</p><h3 data-id="module-resolution">Module Resolution</h3><p>The CLI uses will mostly resolve files using node module resolution. This means you can import files in 2 different ways.</p><h4 data-id="module">Module</h4><p>Importing something from <code class="code codeInline" spellcheck="false" tabindex="0">node_modules</code> is simple. If you’ve installed a package with <code class="code codeInline" spellcheck="false" tabindex="0">yarn add <package-name></code> that module will be available with</p><pre class="code codeBlock" spellcheck="false" tabindex="0">import "package-name"; </pre><p>The actual entry point is determined by the key <code class="code codeInline" spellcheck="false" tabindex="0">main</code> in the package’s <code class="code codeInline" spellcheck="false" tabindex="0">package.json</code>.</p><h4 data-id="relative-path">Relative path</h4><p>You can include your own files by using relative paths</p><pre class="code codeBlock" spellcheck="false" tabindex="0">import {someFunction} from "../file-in-parent-directory"; import {someOtherFunction} from "../sibling-file"; </pre><p>If you are importing a file ending in <code class="code codeInline" spellcheck="false" tabindex="0">.js</code> or <code class="code codeInline" spellcheck="false" tabindex="0">.jsx</code> you do not need to and should not provide a file extension.</p><h2 data-id="sass">Sass</h2><p>Sass partials can be required as usual with</p><pre class="code codeBlock" spellcheck="false" tabindex="0">@import "./_some-relative-partial.scss"; // You don't actually need the extension @import "./_some-relative-partial"; // Or the ./ @import "_some-relative-partial"; // Or the _ @import "some-relative-partial"; </pre><p>The CLI provides some additional import syntax to make importing stylesheet dependancies easier. If a node module dependancy defines a key <code class="code codeInline" spellcheck="false" tabindex="0">style</code> in its <code class="code codeInline" spellcheck="false" tabindex="0">package.json</code> and that points to a .scss or .css file, or if it defines a key <code class="code codeInline" spellcheck="false" tabindex="0">main</code> that points to a .scss or .css file, that file can be loaded using a special syntax.</p><p>So if your folder structure looked like this</p><p>|–my-addon |–src |–scss |–some-entry-file.scss |–_not-an-entry-file.scss |–node_modules |–some-module |–package.json |–some-directory |–somefile.scss</p><p>And the package.json defined <code class="code codeInline" spellcheck="false" tabindex="0">style</code> or <code class="code codeInline" spellcheck="false" tabindex="0">main</code> pointing to <code class="code codeInline" spellcheck="false" tabindex="0">somefile.scss</code></p><p><strong>some-entry-file.scss</strong></p><pre class="code codeBlock" spellcheck="false" tabindex="0">// you could use this @import "~module-name"; // Instead of this @import "../../node_modules/some-module/some-directory/somefile.scss"; </pre><p>Using this type of import makes scss modules easier to consume and is already used in different modules on npm. If you want to use a module that doesn’t have a <code class="code codeInline" spellcheck="false" tabindex="0">style</code> key in it’s package.json you can use the relative path import, but consider making a PR on the project!</p><h2 data-id="less">Less</h2><p>Less partials can be required with</p><pre class="code codeBlock" spellcheck="false" tabindex="0">@import "./_some-relative-partial.less"; // Or if the file is directly relative @import "_some-relative-partial.less"; </pre><p>The full file name is required for Less imports.</p> </article> </main>