Skip to content

Instantly share code, notes, and snippets.

@sep2
Last active March 7, 2020 14:14
Show Gist options
  • Save sep2/4e4219c217192b56267a370e6a00fe1b to your computer and use it in GitHub Desktop.
Save sep2/4e4219c217192b56267a370e6a00fe1b to your computer and use it in GitHub Desktop.
Parcel v1 change build output dir instead of a flatten structure
const fs = require('fs')
const path = require('path')
const replace = require('replace-in-file')
const escapeRegExp = require('lodash.escaperegexp')
// the directory in which you're outputting your build (come from parcel)
const basePath = path.resolve(__dirname, 'dist')
console.log('basePath', basePath)
// the file lists remain location unchanged
const blackList = ['manifest.webmanifest']
// the name for the directory where your static files will be moved to
const assetDir = 'assets'
// the directory where your built files (css and JavaScript) will be moved to
const compiledDir = 'compiled'
// if the assetDir directory isn't there, create it
if (!fs.existsSync(path.join(basePath, assetDir))) {
fs.mkdirSync(path.join(basePath, assetDir))
}
// same for the compiledDir directory
if (!fs.existsSync(path.join(basePath, compiledDir))) {
fs.mkdirSync(path.join(basePath, compiledDir))
}
const globalResult = {}
function replaceFile({ filePath, names, fromFn, toFn, reason }) {
names.forEach(name => {
const fromString = fromFn(name)
const toString = toFn(name)
const options = {
files: filePath,
from: fromString,
to: toString,
countMatches: true,
}
try {
const r = replace
.sync(options)
.map(changedFile => ({
from: fromString,
to: toString,
matches: changedFile.numMatches,
replaced: changedFile.numReplacements,
reason: reason,
}))
.filter(x => x.matches || x.replaced)
if (r.length !== 0) {
globalResult[filePath] = (globalResult[filePath] || []).concat(r)
}
} catch (error) {
console.error('Error occurred:', error)
}
})
}
// Loop through the basePath directory
fs.readdir(basePath, (err, files) => {
// store all files in custom arrays by type
let html = []
let js = []
let css = []
let maps = []
let assetFiles = []
files.forEach(file => {
// first HTML files
if (file.match(/.+\.(html)$/) && !blackList.includes(file)) {
html.push(file)
} else if (file.match(/.+\.(js)$/) && !blackList.includes(file)) {
// then JavaScripts
js.push(file)
} else if (file.match(/.+\.(map)$/) && !blackList.includes(file)) {
// then CSS
maps.push(file)
} else if (file.match(/.+\.(css)$/) && !blackList.includes(file)) {
// then sourcemaps
css.push(file)
} else if (file.match(/.+\..+$/) && !blackList.includes(file)) {
// all other files, exclude current directory and directory one level up
assetFiles.push(file)
}
})
// check what went where
console.table({
html,
css,
js,
assetFiles,
})
// create an array for all compiled assets
let compiledFiles = css.concat(js).concat(maps)
// replace all other resources in html
html.forEach(file => {
replaceFile({
reason: 'html static assets',
filePath: path.join(basePath, file),
names: assetFiles,
fromFn: name => new RegExp(escapeRegExp(name), 'g'),
toFn: name => assetDir + '/' + name,
})
replaceFile({
reason: 'html compiled files',
filePath: path.join(basePath, file),
names: compiledFiles,
fromFn: name => new RegExp(escapeRegExp(name), 'g'),
toFn: name => compiledDir + '/' + name,
})
})
// replace source map links in js
js.forEach(file => {
replaceFile({
reason: 'js source map',
filePath: path.join(basePath, file),
names: maps,
fromFn: name => new RegExp(escapeRegExp(name), 'g'),
toFn: name => compiledDir + '/' + name,
})
})
// replace source map links in css
css.forEach(file => {
replaceFile({
reason: 'css source map',
filePath: path.join(basePath, file),
names: maps,
fromFn: name => new RegExp(escapeRegExp(name), 'g'),
toFn: name => compiledDir + '/' + name,
})
})
// replace static assets links in css
css.forEach(file => {
replaceFile({
reason: 'css static assets',
filePath: path.join(basePath, file),
names: assetFiles,
fromFn: name => new RegExp(escapeRegExp(name), 'g'),
toFn: name => assetDir + '/' + name,
})
})
// special review for manifest
replaceFile({
reason: 'manifest rewrite',
filePath: path.join(basePath, 'manifest.webmanifest'),
names: assetFiles,
fromFn: name => new RegExp(escapeRegExp(name), 'g'),
toFn: name => assetDir + '/' + name,
})
Object.keys(globalResult).forEach(key => {
console.group(key)
console.table(globalResult[key])
console.groupEnd()
})
// move js and css and maps
compiledFiles.forEach(name => {
fs.rename(path.join(basePath, name), path.join(basePath, compiledDir, name), function(err) {
if (err) throw err
console.log(`Successfully moved ${name}`)
})
})
// move staticAssets
assetFiles.forEach(name => {
fs.rename(path.join(basePath, name), path.join(basePath, assetDir, name), function(err) {
if (err) throw err
console.log(`Successfully moved ${name}`)
})
})
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment