Plug Shopify Theme Tools
How to Use
- Required project directory structure:
- Project
- theme
- scripts (optional, can be named whatever you like)
- styles (optional, can be named whatever you like)
- Note, if only the theme directory is present, this application will do nothing.
- Project
- Navigate to Project directory.
$ npm init
$ npm i @plugdigital/shopify-theme-build-tools
- Create the run.js file, adding it to the Project directory (see example below).
Example Run File
import pathTools from "path";
import { fileURLToPath } from "url";
import start from "@plugdigital/shopify-theme-build-tools";
import TerserPlugin from "terser-webpack-plugin";
// The __dirname node global variable is not available in modules,
// which is why we have to do it this way.
const __filename = fileURLToPath(import.meta.url);
const __dirname = pathTools.dirname(__filename);
// The 'scripts' and 'stylesheets' paths are optional, however if BOTH
// are missing, then the app does nothing. So you should always have at
// least one or the other, when using this app.
const paths = {
base: __dirname, // required
themeAssets: pathTools.join(__dirname, "theme", "assets"), // required
scripts: pathTools.join(__dirname, "scripts"),
stylesheets: pathTools.join(__dirname, "styles"),
};
const jsMinificationSettings = {
minimizer: [
new TerserPlugin({
parallel: true,
extractComments: true,
terserOptions: {
// When true, this option changes the code to make it more terse.
compress: false,
// When true, this option mangles the variable and function names.
mangle: false,
}
})
]
};
// Start watching files.
start({
paths,
scriptSettings: {
// You can use any webpack configuration that you like, and since webpack
// is well documented, it is easy to find information about how to
// customize your config to suit your needs.
// We implement the file watching ourselves, so the 'entry' property is
// required on every config object so that we can determine the
// appropriate config to use when a JS file we are watching changes.
webpackConfigs: [
// When you want to package a module into a single file, you can use a
// config object like the following. The 'entry' property specifies the
// path to the module that we want to package. When any file in that
// directory changes, webpack will look for an 'index.js' file, and
// package it along with all of its dependencies into a single file.
{
mode: "production",
entry: pathTools.join(paths.scripts, "base"),
output: {
path: paths.themeAssets,
filename: "plug-base.js"
},
optimization: jsMinificationSettings
}
],
// Optional, a function which will be called every time a JS file is
// changed which has no configuration specified in 'webpackConfigs'.
// If this function is undefined, and a file has no configuration
// specified in 'webpackConfigs', then that file will be ignored.
createSingleFileWebpackConfig: function (inputPath) {
const parsedInputPath = pathTools.parse(inputPath);
const inputFilename = parsedInputPath.base;
return {
mode: "production",
entry: inputPath,
output: {
path: paths.themeAssets,
filename: inputFilename
},
optimization: jsMinificationSettings
};
}
},
stylesheetSettings: {
// Shopify minifies and caches all CSS files now, so this is not necessary
// unless you need to remove comments or something.
minify: false
}
});
Example Project Structure
Note, the scripts and stylesheets below
- theme
- assets
- config
- layout
- locales
- sections
- snippets
- templates
- scripts
- base <-- This module will be packaged into a single file.
- globalComponents
- header.js
- footer.js
- cartDrawer.js
- events.js
- utils.js
- index.js <-- This file is the entry point for the 'base' module.
- globalComponents
- mobile-nav.js
- cart.js
- ...
- base <-- This module will be packaged into a single file.
- styles
- plug-base
- _buttons.scss
- _forms.scss
- plug-base.scss
- component-mobile-nav.css
- section-blog-post-main.scss
- section-header.scss
- ...
- plug-base
Stylesheets
-
The stylesheets must be .scss files. We can add support for Less or other preprocessing 'languages' as needed.
-
When stylesheets whose filename starts with an underscore are changed, it triggers the compilation and minification of the first file in their directory which is not prefaced with an underscore. All other stylesheets are compiled and minified individually, and copied to theme/assets/.
Recommended Usage
-
SCSS files should be compiled to CSS but not minified. This is because Shopify minifies CSS files and caches the result the first time they are requested.
-
For JS files, we do minify them (until we can confirm that Shopify automatically minifies them), but we ONLY REMOVE WHITESPACE AND COMMENTS. Anything that rewrites the JS in a more terse manner should be avoided. This ensures that JS is easy to debug in the browser without having to upload sourcemaps too. For anyone needing to read a minified script, sites like unminify.com will make it legible, and again, since we aren't modifying the code itself, any unminifier tool should output readable code.