-
-
Save afridley/50f61fc1b3f31035c7d7ffd00275ea96 to your computer and use it in GitHub Desktop.
Webpack 4 Config for WordPress plugin, theme, and block development
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
**/*.min.js | |
**/*.build.js | |
**/node_modules/** | |
**/vendor/** | |
build | |
coverage | |
cypress | |
node_modules | |
vendor |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"root": true, | |
"parser": "babel-eslint", | |
"extends": [ | |
"wordpress", | |
"plugin:react/recommended", | |
"plugin:jsx-a11y/recommended", | |
"plugin:jest/recommended" | |
], | |
"env": { | |
"browser": false, | |
"es6": true, | |
"node": true, | |
"mocha": true, | |
"jest/globals": true | |
}, | |
"parserOptions": { | |
"sourceType": "module", | |
"ecmaFeatures": { | |
"jsx": true | |
} | |
}, | |
"globals": { | |
"wp": true, | |
"wpApiSettings": true, | |
"window": true, | |
"document": true | |
}, | |
"plugins": [ | |
"react", | |
"jsx-a11y", | |
"jest" | |
], | |
"settings": { | |
"react": { | |
"pragma": "wp" | |
} | |
}, | |
"rules": { | |
"array-bracket-spacing": [ | |
"error", | |
"always" | |
], | |
"brace-style": [ | |
"error", | |
"1tbs" | |
], | |
"camelcase": [ | |
"error", | |
{ | |
"properties": "never" | |
} | |
], | |
"comma-dangle": [ | |
"error", | |
"always-multiline" | |
], | |
"comma-spacing": "error", | |
"comma-style": "error", | |
"computed-property-spacing": [ | |
"error", | |
"always" | |
], | |
"constructor-super": "error", | |
"dot-notation": "error", | |
"eol-last": "error", | |
"eqeqeq": "error", | |
"func-call-spacing": "error", | |
"indent": [ | |
"error", | |
"tab", | |
{ | |
"SwitchCase": 1 | |
} | |
], | |
"jsx-a11y/label-has-for": [ | |
"error", | |
{ | |
"required": "id" | |
} | |
], | |
"jsx-a11y/media-has-caption": "off", | |
"jsx-a11y/no-noninteractive-tabindex": "off", | |
"jsx-a11y/role-has-required-aria-props": "off", | |
"jsx-quotes": "error", | |
"key-spacing": "error", | |
"keyword-spacing": "error", | |
"lines-around-comment": "off", | |
"no-alert": "error", | |
"no-bitwise": "error", | |
"no-caller": "error", | |
"no-console": "error", | |
"no-const-assign": "error", | |
"no-debugger": "error", | |
"no-dupe-args": "error", | |
"no-dupe-class-members": "error", | |
"no-dupe-keys": "error", | |
"no-duplicate-case": "error", | |
"no-duplicate-imports": "error", | |
"no-else-return": "error", | |
"no-eval": "error", | |
"no-extra-semi": "error", | |
"no-fallthrough": "error", | |
"no-lonely-if": "error", | |
"no-mixed-operators": "error", | |
"no-mixed-spaces-and-tabs": "error", | |
"no-multiple-empty-lines": [ | |
"error", | |
{ | |
"max": 1 | |
} | |
], | |
"no-multi-spaces": "error", | |
"no-multi-str": "off", | |
"no-negated-in-lhs": "error", | |
"no-nested-ternary": "error", | |
"no-redeclare": "error", | |
"no-restricted-syntax": [ | |
"error", | |
{ | |
"selector": "ImportDeclaration[source.value=/^@wordpress\\u002F.+\\u002F/]", | |
"message": "Path access on WordPress dependencies is not allowed." | |
}, | |
{ | |
"selector": "ImportDeclaration[source.value=/^blocks$/]", | |
"message": "Use @wordpress/blocks as import path instead." | |
}, | |
{ | |
"selector": "ImportDeclaration[source.value=/^components$/]", | |
"message": "Use @wordpress/components as import path instead." | |
}, | |
{ | |
"selector": "ImportDeclaration[source.value=/^date$/]", | |
"message": "Use @wordpress/date as import path instead." | |
}, | |
{ | |
"selector": "ImportDeclaration[source.value=/^editor$/]", | |
"message": "Use @wordpress/editor as import path instead." | |
}, | |
{ | |
"selector": "ImportDeclaration[source.value=/^element$/]", | |
"message": "Use @wordpress/element as import path instead." | |
}, | |
{ | |
"selector": "ImportDeclaration[source.value=/^i18n$/]", | |
"message": "Use @wordpress/i18n as import path instead." | |
}, | |
{ | |
"selector": "ImportDeclaration[source.value=/^data$/]", | |
"message": "Use @wordpress/data as import path instead." | |
}, | |
{ | |
"selector": "ImportDeclaration[source.value=/^utils$/]", | |
"message": "Use @wordpress/utils as import path instead." | |
}, | |
{ | |
"selector": "CallExpression[callee.name=/^__|_n|_x$/]:not([arguments.0.type=/^Literal|BinaryExpression$/])", | |
"message": "Translate function arguments must be string literals." | |
}, | |
{ | |
"selector": "CallExpression[callee.name=/^_n|_x$/]:not([arguments.1.type=/^Literal|BinaryExpression$/])", | |
"message": "Translate function arguments must be string literals." | |
}, | |
{ | |
"selector": "CallExpression[callee.name=_nx]:not([arguments.2.type=/^Literal|BinaryExpression$/])", | |
"message": "Translate function arguments must be string literals." | |
} | |
], | |
"no-shadow": "error", | |
"no-undef": "error", | |
"no-undef-init": "error", | |
"no-unreachable": "error", | |
"no-unsafe-negation": "error", | |
"no-unused-expressions": "error", | |
"no-unused-vars": "error", | |
"no-useless-computed-key": "error", | |
"no-useless-constructor": "error", | |
"no-useless-return": "error", | |
"no-var": "error", | |
"no-whitespace-before-property": "error", | |
"object-curly-spacing": [ | |
"error", | |
"always" | |
], | |
"prefer-const": "error", | |
"quote-props": [ | |
"error", | |
"as-needed" | |
], | |
"react/display-name": "off", | |
"react/jsx-curly-spacing": [ | |
"error", | |
{ | |
"when": "never", | |
"children": true | |
} | |
], | |
"react/jsx-equals-spacing": "error", | |
"react/jsx-indent": [ | |
"error", | |
"tab" | |
], | |
"react/jsx-indent-props": [ | |
"error", | |
"tab" | |
], | |
"react/jsx-key": "error", | |
"react/jsx-tag-spacing": "error", | |
"react/no-children-prop": "off", | |
"react/no-find-dom-node": "warn", | |
"react/prop-types": "off", | |
"semi": "error", | |
"semi-spacing": "error", | |
"space-before-blocks": [ | |
"error", | |
"always" | |
], | |
"space-before-function-paren": [ | |
"error", | |
"never" | |
], | |
"space-in-parens": [ | |
"error", | |
"always" | |
], | |
"space-infix-ops": [ | |
"error", | |
{ | |
"int32Hint": false | |
} | |
], | |
"space-unary-ops": [ | |
"error" | |
], | |
"template-curly-spacing": [ | |
"error", | |
"always" | |
], | |
"valid-jsdoc": [ | |
"error", | |
{ | |
"requireReturn": false | |
} | |
], | |
"valid-typeof": "error", | |
"yoda": "off" | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "my-thing", | |
"description": "A description of my thing.", | |
"author": "Micah Wood <[email protected]> (http://wpscholar.com)", | |
"license": "proprietary", | |
"private": true, | |
"scripts": { | |
"build": "cross-env NODE_ENV=production webpack", | |
"lint": "eslint build/js/**/*", | |
"start": "webpack --watch", | |
"test": "echo \"Error: no test specified\" && exit 1" | |
}, | |
"dependencies": { | |
"classnames": "^2.2.5" | |
}, | |
"devDependencies": { | |
"@babel/core": "^7.1.2", | |
"@wordpress/babel-plugin-makepot": "^2.1.1", | |
"@wordpress/babel-preset-default": "^3.0.0", | |
"@wordpress/browserslist-config": "^2.1.3", | |
"@wordpress/i18n": "^3.0.0", | |
"ajv": "^6.5.4", | |
"autoprefixer": "^9.1.5", | |
"babel-eslint": "^10.0.1", | |
"babel-loader": "^8.0.4", | |
"babel-plugin-transform-class-properties": "^6.24.1", | |
"cross-env": "^5.0.1", | |
"css-loader": "^1.0.0", | |
"eslint": "^5.6.1", | |
"eslint-config-wordpress": "^2.0.0", | |
"eslint-plugin-jest": "^21.6.1", | |
"eslint-plugin-jsx-a11y": "^6.0.3", | |
"eslint-plugin-react": "^7.5.1", | |
"eslint-plugin-wordpress": "^0.1.0", | |
"file-loader": "^2.0.0", | |
"import-glob": "^1.5.0", | |
"mini-css-extract-plugin": "^0.4.0", | |
"node-sass": "^4.9.0", | |
"node-sass-glob-importer": "^5.1.2", | |
"postcss-loader": "^3.0.0", | |
"raw-loader": "^0.5.1", | |
"sass-loader": "^7.0.1", | |
"style-loader": "^0.23.0", | |
"webpack": "^4.20.2", | |
"webpack-cli": "^3.1.1" | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
const autoprefixer = require( 'autoprefixer' ); | |
const fs = require( 'fs' ); | |
const globImporter = require( 'node-sass-glob-importer' ); | |
const browsers = require( '@wordpress/browserslist-config' ); | |
const MiniCssExtractPlugin = require( 'mini-css-extract-plugin' ); | |
const path = require( 'path' ); | |
const webpack = require( 'webpack' ); | |
module.exports = function() { | |
const mode = process.env.NODE_ENV || 'development'; | |
const extensionPrefix = mode === 'production' ? '.min' : ''; | |
// This is the URL path relative to the root domain. | |
const publicPath = '/wp-content/mu-plugins/blocks/'; | |
// These are the paths where different types of resources should end up. | |
const paths = { | |
css: 'assets/css/', | |
img: 'assets/img/', | |
font: 'assets/font/', | |
js: 'assets/js/', | |
lang: 'languages/', | |
}; | |
// The property names will be the file names, the values are the files that should be included. | |
const entry = { | |
blocks: [ | |
'./build/scss/blocks.scss', | |
], | |
editor: [ | |
'./build/js/editor.js', | |
'./build/scss/editor.scss', | |
], | |
}; | |
const loaders = { | |
css: { | |
loader: 'css-loader', | |
options: { | |
sourceMap: true, | |
}, | |
}, | |
postCss: { | |
loader: 'postcss-loader', | |
options: { | |
plugins: [ | |
autoprefixer( { | |
browsers, | |
flexbox: 'no-2009', | |
} ), | |
], | |
sourceMap: true, | |
}, | |
}, | |
sass: { | |
loader: 'sass-loader', | |
options: { | |
importer: globImporter(), | |
sourceMap: true, | |
}, | |
}, | |
}; | |
const config = { | |
mode, | |
entry, | |
output: { | |
path: path.join( __dirname, '/' ), | |
publicPath, | |
filename: `${ paths.js }[name]${ extensionPrefix }.js`, | |
}, | |
externals: { | |
'@wordpress/a11y': 'wp.a11y', | |
'@wordpress/components': 'wp.components', // Not really a package. | |
'@wordpress/blocks': 'wp.blocks', // Not really a package. | |
'@wordpress/data': 'wp.data', // Not really a package. | |
'@wordpress/date': 'wp.date', // Not really a package. | |
'@wordpress/element': 'wp.element', // Not really a package. | |
'@wordpress/hooks': 'wp.hooks', | |
'@wordpress/i18n': 'wp.i18n', | |
'@wordpress/utils': 'wp.utils', // Not really a package | |
backbone: 'Backbone', | |
jquery: 'jQuery', | |
lodash: 'lodash', | |
moment: 'moment', | |
react: 'React', | |
'react-dom': 'ReactDOM', | |
tinymce: 'tinymce', | |
}, | |
module: { | |
rules: [ | |
{ | |
enforce: 'pre', | |
test: /\.js|.jsx/, | |
loader: 'import-glob', | |
exclude: /(node_modules)/, | |
}, | |
{ | |
test: /\.js|.jsx/, | |
loader: 'babel-loader', | |
query: { | |
presets: [ | |
'@wordpress/default', | |
], | |
plugins: [ | |
[ | |
'@wordpress/babel-plugin-makepot', | |
{ | |
'output': `${ paths.lang }translation.pot`, | |
} | |
], | |
'transform-class-properties', | |
], | |
}, | |
exclude: /(node_modules|bower_components)/, | |
}, | |
{ | |
test: /\.html$/, | |
loader: 'raw-loader', | |
exclude: /node_modules/, | |
}, | |
{ | |
test: /\.css$/, | |
use: [ | |
MiniCssExtractPlugin.loader, | |
loaders.css, | |
loaders.postCss, | |
], | |
exclude: /node_modules/, | |
}, | |
{ | |
test: /\.scss$/, | |
use: [ | |
MiniCssExtractPlugin.loader, | |
loaders.css, | |
loaders.postCss, | |
loaders.sass, | |
], | |
exclude: /node_modules/, | |
}, | |
{ | |
test: /\.(ttf|eot|svg|woff2?)(\?v=[0-9]\.[0-9]\.[0-9])?$/, | |
use: [ | |
{ | |
loader: 'file-loader', | |
options: { | |
name: '[name].[ext]', | |
outputPath: paths.font, | |
}, | |
}, | |
], | |
exclude: /(assets)/, | |
}, | |
], | |
}, | |
plugins: [ | |
new MiniCssExtractPlugin( { | |
filename: `${ paths.css }[name]${ extensionPrefix }.css`, | |
} ), | |
new webpack.DefinePlugin( { | |
'process.env.NODE_ENV': JSON.stringify( mode ), | |
} ), | |
function() { | |
// Custom webpack plugin - remove generated JS files that aren't needed | |
this.hooks.done.tap( 'webpack', function( stats ) { | |
stats.compilation.chunks.forEach( chunk => { | |
if ( ! chunk.entryModule._identifier.includes( '.js' ) ) { | |
chunk.files.forEach( file => { | |
if ( file.includes( '.js' ) ) { | |
fs.unlinkSync( path.join( __dirname, `/${ file }` ) ); | |
} | |
} ); | |
} | |
} ); | |
} ); | |
}, | |
], | |
}; | |
if ( mode !== 'production' ) { | |
config.devtool = 'source-map'; | |
} | |
return config; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment