Upgrade to Webpack 4 (#1214)
This commit is contained in:
parent
80817e2157
commit
4d981d8e01
3
.babelrc
3
.babelrc
@ -33,7 +33,8 @@
|
||||
}],
|
||||
"transform-export-extensions",
|
||||
"transform-class-properties",
|
||||
"transform-object-rest-spread"
|
||||
"transform-object-rest-spread",
|
||||
"react-hot-loader/babel",
|
||||
],
|
||||
"env": {
|
||||
"test": {
|
||||
|
@ -4,9 +4,7 @@
|
||||
],
|
||||
"settings": {
|
||||
"import/resolver": {
|
||||
"webpack": {
|
||||
"config": "webpack.dev.js"
|
||||
}
|
||||
"babel-module": {}
|
||||
}
|
||||
},
|
||||
"globals": {
|
||||
|
36
package.json
36
package.json
@ -5,12 +5,11 @@
|
||||
"main": "dist/cms.js",
|
||||
"scripts": {
|
||||
"start": "npm run dev",
|
||||
"dev": "webpack-dev-server -d --config webpack.dev.js",
|
||||
"dev:write": "webpack-dev-server -d --config webpack.dev-write.js",
|
||||
"dev": "webpack-dev-server --env.development",
|
||||
"dev:write": "webpack-dev-server --env.development --env.write",
|
||||
"test": "jest --coverage",
|
||||
"test:watch": "jest --watch",
|
||||
"build": "cross-env NODE_ENV=production webpack --config webpack.prod.js --display-error-details",
|
||||
"build:scripts": "cross-env NODE_ENV=production webpack --config webpack.cli.js",
|
||||
"build": "cross-env NODE_ENV=production webpack-cli --display-error-details --env.production",
|
||||
"add-contributor": "all-contributors add",
|
||||
"generate-contributors": "all-contributors generate",
|
||||
"lint": "npm run lint:js & npm run lint:css",
|
||||
@ -77,7 +76,7 @@
|
||||
"babel-cli": "^6.18.0",
|
||||
"babel-core": "^6.23.1",
|
||||
"babel-jest": "^22.0.0",
|
||||
"babel-loader": "^7.0.0",
|
||||
"babel-loader": "^7.1.4",
|
||||
"babel-plugin-lodash": "^3.2.0",
|
||||
"babel-plugin-module-resolver": "^3.0.0",
|
||||
"babel-plugin-transform-builtin-extend": "^1.1.0",
|
||||
@ -89,30 +88,30 @@
|
||||
"babel-preset-env": "^1.6.0",
|
||||
"babel-preset-react": "^6.23.0",
|
||||
"babel-runtime": "^6.23.0",
|
||||
"cross-env": "^5.0.2",
|
||||
"css-loader": "^0.28.7",
|
||||
"cross-env": "^5.1.4",
|
||||
"css-loader": "^0.28.11",
|
||||
"cssnano": "^v4.0.0-rc.2",
|
||||
"deep-equal": "^1.0.1",
|
||||
"enzyme": "^3.1.0",
|
||||
"enzyme-adapter-react-16": "^1.0.2",
|
||||
"eslint": "^3.7.1",
|
||||
"eslint-config-netlify": "github:netlify/eslint-config-netlify",
|
||||
"eslint-import-resolver-webpack": "^0.8.3",
|
||||
"exports-loader": "^0.6.4",
|
||||
"extract-text-webpack-plugin": "^3.0.0",
|
||||
"file-loader": "^1.1.4",
|
||||
"eslint-import-resolver-babel-module": "^4.0.0",
|
||||
"exports-loader": "^0.7.0",
|
||||
"file-loader": "^1.1.11",
|
||||
"identity-obj-proxy": "^3.0.0",
|
||||
"imports-loader": "^0.7.1",
|
||||
"imports-loader": "^0.8.0",
|
||||
"jest": "^22.0.0",
|
||||
"jest-cli": "^22.0.0",
|
||||
"lint-staged": "^3.3.1",
|
||||
"mini-css-extract-plugin": "^0.4.0",
|
||||
"npm-check": "^5.2.3",
|
||||
"postcss-cssnext": "^3.0.2",
|
||||
"postcss-import": "^11.0.0",
|
||||
"postcss-loader": "^2.0.7",
|
||||
"postcss-loader": "^2.1.3",
|
||||
"raf": "^3.4.0",
|
||||
"react-test-renderer": "^16.0.0",
|
||||
"style-loader": "^0.18.2",
|
||||
"style-loader": "^0.20.3",
|
||||
"stylefmt": "^4.3.1",
|
||||
"stylelint": "^7.9.0",
|
||||
"stylelint-config-css-modules": "^0.1.0",
|
||||
@ -120,11 +119,9 @@
|
||||
"stylelint-declaration-block-order": "^0.1.0",
|
||||
"stylelint-declaration-use-variable": "^1.6.0",
|
||||
"svg-inline-loader": "^0.8.0",
|
||||
"uglifyjs-webpack-plugin": "^1.0.1",
|
||||
"webpack": "^3.6.0",
|
||||
"webpack-dev-server": "^2.9.1",
|
||||
"webpack-merge": "^4.1.0",
|
||||
"webpack-postcss-tools": "^1.1.1",
|
||||
"webpack": "^4.4.1",
|
||||
"webpack-cli": "^2.0.13",
|
||||
"webpack-dev-server": "^3.1.3",
|
||||
"write-file-webpack-plugin": "^4.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
@ -154,6 +151,7 @@
|
||||
"react-dnd-html5-backend": "^2.5.4",
|
||||
"react-dom": "^16.0.0",
|
||||
"react-frame-component": "^2.0.0",
|
||||
"react-hot-loader": "^4.0.0",
|
||||
"react-immutable-proptypes": "^2.1.0",
|
||||
"react-is": "16.3.1",
|
||||
"react-modal": "^3.1.5",
|
||||
|
@ -1,150 +0,0 @@
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import process from "process";
|
||||
import yaml from 'js-yaml';
|
||||
import deepEqual from 'deep-equal';
|
||||
import { formatByExtension } from "../src/formats/formats";
|
||||
|
||||
const looksLikeMarkdown = /(\[.+\]\(.+\)|\n?[#]+ [a-z0-9])/; // eslint-disable-line
|
||||
const looksLikeAnImage = /^[^ ]+\.(png|jpg|svg|gif|jpeg)/;
|
||||
|
||||
function capitalize(name) {
|
||||
return name.substr(0, 1).toUpperCase() + name.substr(1);
|
||||
}
|
||||
|
||||
function inferWidget(name, value) {
|
||||
if (value == null) {
|
||||
return { widget: 'string' };
|
||||
}
|
||||
if (value instanceof Date) {
|
||||
return { widget: value.toJSON().match(/T00:00:00\.000Z$/) ? 'date' : 'datetime' };
|
||||
}
|
||||
if (value instanceof Array) {
|
||||
if (typeof value[0] === 'string') {
|
||||
return { widget: 'list' };
|
||||
}
|
||||
return { widget: 'list', fields: inferFields(value) };
|
||||
}
|
||||
if (typeof value === 'object') {
|
||||
return { widget: 'object', fields: inferFields([value]) };
|
||||
}
|
||||
if (value === false || value === true) {
|
||||
return { widget: 'checkbox' };
|
||||
}
|
||||
if (typeof value === 'number') {
|
||||
return { widget: 'number' };
|
||||
}
|
||||
if (name === 'body' || value.match(looksLikeMarkdown)) {
|
||||
return { widget: 'markdown' };
|
||||
}
|
||||
if (value.match(/\n/)) {
|
||||
return { widget: 'text' };
|
||||
}
|
||||
if (value.match(looksLikeAnImage)) {
|
||||
return { widget: 'image' };
|
||||
}
|
||||
return { widget: 'string' };
|
||||
}
|
||||
|
||||
function inferField(name, value) {
|
||||
return Object.assign({
|
||||
label: capitalize(name.replace(/_-/g, ' ')),
|
||||
name,
|
||||
}, inferWidget(name, value));
|
||||
}
|
||||
|
||||
function inferFields(entries) {
|
||||
const fields = {};
|
||||
entries.forEach((entry) => {
|
||||
if (entry == null) { return; }
|
||||
Object.keys(entry).forEach((fieldName) => {
|
||||
const field = inferField(fieldName, entry[fieldName]);
|
||||
if (fields[fieldName]) {
|
||||
fields[fieldName] = combineFields(fields[fieldName], field);
|
||||
} else {
|
||||
fields[fieldName] = field;
|
||||
}
|
||||
});
|
||||
});
|
||||
return Object.keys(fields).map(key => fields[key]);
|
||||
}
|
||||
|
||||
const widgetRank = {
|
||||
markdown: 1,
|
||||
text: 2,
|
||||
string: 3,
|
||||
image: 4,
|
||||
datetime: 4,
|
||||
date: 5,
|
||||
number: 5,
|
||||
object: 7,
|
||||
list: 7,
|
||||
};
|
||||
|
||||
function compareWidget(a, b) {
|
||||
return widgetRank[a] - widgetRank[b];
|
||||
}
|
||||
|
||||
function combineFields(a, b) {
|
||||
if (b == null && a) {
|
||||
return a;
|
||||
}
|
||||
if (a == null && b) {
|
||||
return b;
|
||||
}
|
||||
if (deepEqual(a, b)) {
|
||||
return a;
|
||||
}
|
||||
if (a.widget === b.widget) {
|
||||
if (a.fields && b.fields) {
|
||||
const newFields = {};
|
||||
a.fields.forEach((field) => {
|
||||
newFields[field.name] = combineFields(field, b.fields.find(f => f.name === field.name));
|
||||
});
|
||||
b.fields.forEach((field) => {
|
||||
if (!newFields[field.name]) {
|
||||
newFields[field.name] = field;
|
||||
}
|
||||
});
|
||||
return Object.assign({}, a, { fields: Object.keys(newFields).map(k => newFields[k]) });
|
||||
}
|
||||
return a;
|
||||
}
|
||||
return [a, b].sort((fieldA, fieldB) => compareWidget(fieldB.widget, fieldA.widget))[0];
|
||||
}
|
||||
|
||||
if (process.argv.length !== 3) {
|
||||
console.log("Usage: autoconfigure.collections.js <path-to-my-folder>");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const folder = process.argv[2].replace(/\/$/, '');
|
||||
const files = fs.readdirSync(folder);
|
||||
const extensions = {};
|
||||
|
||||
files.forEach((file) => {
|
||||
const ext = file.split(".").pop();
|
||||
if (ext) {
|
||||
extensions[ext] = extensions[ext] || 0;
|
||||
extensions[ext] += 1;
|
||||
}
|
||||
});
|
||||
|
||||
const name = folder.split('/').filter(s => s).pop();
|
||||
const extension = Object.keys(extensions).sort((a, b) => extensions[b] - extensions[a])[0];
|
||||
const format = formatByExtension(extension);
|
||||
const entries = files.filter(name => name.split(".").pop() === extension).slice(0, 100).map(file => (
|
||||
format.fromFile(fs.readFileSync(path.join(folder, file), { encoding: 'utf8' }))
|
||||
));
|
||||
const fields = inferFields(entries);
|
||||
|
||||
|
||||
const collection = {
|
||||
label: capitalize(name),
|
||||
name,
|
||||
folder,
|
||||
extension,
|
||||
fields,
|
||||
};
|
||||
|
||||
console.log(yaml.safeDump([collection], { flowLevel: 3 }));
|
@ -1,5 +1,6 @@
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import { hot } from 'react-hot-loader';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { connect } from 'react-redux';
|
||||
import { Route, Switch, Link, Redirect } from 'react-router-dom';
|
||||
@ -180,4 +181,6 @@ function mapDispatchToProps(dispatch) {
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(App);
|
||||
export default hot(module)(
|
||||
connect(mapStateToProps, mapDispatchToProps)(App)
|
||||
);
|
||||
|
@ -1,54 +0,0 @@
|
||||
/* eslint global-require: 0 */
|
||||
|
||||
const webpack = require('webpack');
|
||||
const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
|
||||
module.exports = {
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.js?$/,
|
||||
use: 'babel-loader',
|
||||
exclude: /node_modules/,
|
||||
},
|
||||
{
|
||||
/* CSS loader for npm modules that are shipped with CSS that should be loaded without processing.
|
||||
List all of theme in the array
|
||||
*/
|
||||
test: /\.css$/,
|
||||
include: [/redux-notifications/],
|
||||
use: ExtractTextPlugin.extract({
|
||||
fallback: 'style-loader',
|
||||
use: 'css-loader',
|
||||
}),
|
||||
},
|
||||
{
|
||||
/* We use PostCSS for CMS styles */
|
||||
test: /\.css$/,
|
||||
exclude: [/node_modules/],
|
||||
use: ExtractTextPlugin.extract({
|
||||
fallback: 'style-loader',
|
||||
use: [
|
||||
{
|
||||
loader: 'css-loader',
|
||||
options: {
|
||||
importLoaders: 1,
|
||||
},
|
||||
},
|
||||
{ loader: 'postcss-loader' },
|
||||
],
|
||||
}),
|
||||
},
|
||||
{
|
||||
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
|
||||
exclude: [/node_modules/],
|
||||
loader: 'svg-inline-loader',
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
new webpack.IgnorePlugin(/^esprima$/, /js-yaml/), // Ignore Esprima import for js-yaml
|
||||
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), // Ignore all optional deps of moment.js
|
||||
],
|
||||
target: 'web', // Make web variables accessible to webpack, e.g. window
|
||||
};
|
@ -1,22 +0,0 @@
|
||||
/* global module, __dirname, require */
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const merge = require('webpack-merge');
|
||||
|
||||
module.exports = merge.smart(require('./webpack.base.js'), {
|
||||
plugins: [
|
||||
new webpack.BannerPlugin('#!/usr/bin/env node', { raw: true }),
|
||||
],
|
||||
entry: {
|
||||
"autoconfigure.collection": './scripts/autoconfigure.collection',
|
||||
},
|
||||
output: {
|
||||
path: path.join(__dirname, 'bin'),
|
||||
filename: '[name].js',
|
||||
},
|
||||
externals: {
|
||||
fs: 'commonjs fs',
|
||||
path: 'commonjs path',
|
||||
process: 'commonjs process',
|
||||
},
|
||||
});
|
118
webpack.config.js
Normal file
118
webpack.config.js
Normal file
@ -0,0 +1,118 @@
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||
const WriteFilePlugin = require('write-file-webpack-plugin');
|
||||
const pkg = require('./package.json');
|
||||
|
||||
function getPlugins(env, argv) {
|
||||
const plugins = [
|
||||
new webpack.IgnorePlugin(/^esprima$/, /js-yaml/), // Ignore Esprima import for js-yaml
|
||||
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), // Ignore all optional deps of moment.js
|
||||
new webpack.DefinePlugin({
|
||||
NETLIFY_CMS_VERSION: JSON.stringify(
|
||||
`${pkg.version}${env.production ? '' : '-dev'}`
|
||||
),
|
||||
}),
|
||||
new webpack.NoEmitOnErrorsPlugin(), // Default for production mode, but adding to development mode
|
||||
];
|
||||
if (env.production) {
|
||||
// Extract CSS
|
||||
plugins.push(
|
||||
new MiniCssExtractPlugin({
|
||||
filename: '[name].css',
|
||||
})
|
||||
);
|
||||
// During beta phase, generate source maps for better errors
|
||||
plugins.push(
|
||||
new webpack.SourceMapDevToolPlugin({
|
||||
// asset matching
|
||||
test: /\.js?$/,
|
||||
|
||||
// file and reference
|
||||
filename: '[file].map',
|
||||
|
||||
// don't include source file content, since we link to the actual file
|
||||
noSources: true,
|
||||
|
||||
// sourcemap is in 'dist', webpack context is in 'src'
|
||||
moduleFilenameTemplate: info =>
|
||||
path.posix.normalize(`../src/${info.resourcePath}`),
|
||||
})
|
||||
);
|
||||
}
|
||||
if (env.development) {
|
||||
plugins.push(new webpack.HotModuleReplacementPlugin());
|
||||
|
||||
if (env.write) {
|
||||
plugins.push(new WriteFilePlugin());
|
||||
}
|
||||
}
|
||||
return plugins;
|
||||
}
|
||||
|
||||
module.exports = function(env, argv) {
|
||||
const plugins = getPlugins(env, argv);
|
||||
|
||||
return {
|
||||
mode: env.production ? 'production' : 'development',
|
||||
entry: {
|
||||
cms: './index',
|
||||
},
|
||||
output: {
|
||||
path: path.join(__dirname, 'dist'),
|
||||
filename: '[name].js',
|
||||
library: 'netlify-cms',
|
||||
libraryTarget: 'umd',
|
||||
umdNamedDefine: true,
|
||||
},
|
||||
context: path.join(__dirname, 'src'),
|
||||
module: {
|
||||
noParse: /localforage\.js/,
|
||||
rules: [
|
||||
{
|
||||
test: /\.js?$/,
|
||||
use: 'babel-loader',
|
||||
exclude: /node_modules/,
|
||||
},
|
||||
{
|
||||
/**
|
||||
* CSS loader for npm modules that are shipped with CSS that should be loaded without processing.
|
||||
* List all of theme in the array
|
||||
*/
|
||||
test: /\.css$/,
|
||||
include: [/redux-notifications/],
|
||||
use: [
|
||||
env.production ? MiniCssExtractPlugin.loader : 'style-loader',
|
||||
'css-loader',
|
||||
],
|
||||
},
|
||||
{
|
||||
/* We use PostCSS for CMS styles */
|
||||
test: /\.css$/,
|
||||
exclude: [/node_modules/],
|
||||
use: [
|
||||
env.production ? MiniCssExtractPlugin.loader : 'style-loader',
|
||||
{
|
||||
loader: 'css-loader',
|
||||
options: {
|
||||
importLoaders: 1,
|
||||
},
|
||||
},
|
||||
{ loader: 'postcss-loader' },
|
||||
],
|
||||
},
|
||||
{
|
||||
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
|
||||
exclude: [/node_modules/],
|
||||
loader: 'svg-inline-loader',
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins,
|
||||
target: 'web', // Make web variables accessible to webpack, e.g. window
|
||||
devServer: {
|
||||
contentBase: 'example/',
|
||||
hot: true,
|
||||
},
|
||||
};
|
||||
};
|
@ -1,9 +0,0 @@
|
||||
/* global require */
|
||||
const merge = require('webpack-merge');
|
||||
const WriteFilePlugin = require('write-file-webpack-plugin');
|
||||
|
||||
module.exports = merge.smart(require('./webpack.dev.js'), {
|
||||
plugins: [
|
||||
new WriteFilePlugin(),
|
||||
],
|
||||
});
|
@ -1,58 +0,0 @@
|
||||
/* global module, __dirname, require */
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const merge = require('webpack-merge');
|
||||
const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
|
||||
const HOST = 'localhost';
|
||||
const PORT = '8080';
|
||||
|
||||
module.exports = merge.smart(require('./webpack.base.js'), {
|
||||
entry: {
|
||||
cms: [
|
||||
`webpack-dev-server/client?http://${ HOST }:${ PORT }/`,
|
||||
'./index',
|
||||
],
|
||||
},
|
||||
output: {
|
||||
path: path.join(__dirname, 'dist'),
|
||||
filename: '[name].js',
|
||||
publicPath: `http://${ HOST }:${ PORT }/`,
|
||||
library: 'netlify-cms',
|
||||
libraryTarget: 'umd',
|
||||
umdNamedDefine: true,
|
||||
},
|
||||
context: path.join(__dirname, 'src'),
|
||||
module: {
|
||||
noParse: /localforage\.js/,
|
||||
loaders: [
|
||||
{
|
||||
loader: path.resolve(__dirname, './node_modules/babel-loader'),
|
||||
test: /\.js?$/,
|
||||
exclude: /node_modules/,
|
||||
},
|
||||
],
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': {
|
||||
NODE_ENV: JSON.stringify('development'),
|
||||
},
|
||||
}),
|
||||
new webpack.DefinePlugin({
|
||||
NETLIFY_CMS_VERSION: JSON.stringify(require("./package.json").version + "-dev"),
|
||||
}),
|
||||
new webpack.NoEmitOnErrorsPlugin(),
|
||||
new ExtractTextPlugin({
|
||||
filename: '[name].css',
|
||||
disable: true,
|
||||
}),
|
||||
],
|
||||
devtool: 'source-map',
|
||||
devServer: {
|
||||
contentBase: 'example/',
|
||||
historyApiFallback: true,
|
||||
disableHostCheck: true,
|
||||
headers: {"Access-Control-Allow-Origin": "*"},
|
||||
},
|
||||
});
|
@ -1,59 +0,0 @@
|
||||
/* global module, __dirname, require */
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const merge = require('webpack-merge');
|
||||
const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
|
||||
|
||||
module.exports = merge.smart(require('./webpack.base.js'), {
|
||||
entry: {
|
||||
cms: './index',
|
||||
},
|
||||
output: {
|
||||
path: path.join(__dirname, 'dist'),
|
||||
filename: '[name].js',
|
||||
library: 'netlify-cms',
|
||||
libraryTarget: 'umd',
|
||||
umdNamedDefine: true,
|
||||
},
|
||||
context: path.join(__dirname, 'src'),
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': {
|
||||
NODE_ENV: JSON.stringify('production'),
|
||||
},
|
||||
}),
|
||||
new webpack.DefinePlugin({
|
||||
NETLIFY_CMS_VERSION: JSON.stringify(require("./package.json").version),
|
||||
}),
|
||||
|
||||
// Combine/hoist module scopes when possible.
|
||||
new webpack.optimize.ModuleConcatenationPlugin(),
|
||||
|
||||
// Minify and optimize the JavaScript
|
||||
new UglifyJsPlugin({
|
||||
sourceMap: true,
|
||||
}),
|
||||
|
||||
// Extract CSS
|
||||
new ExtractTextPlugin({
|
||||
filename: '[name].css',
|
||||
allChunks: true
|
||||
}),
|
||||
|
||||
// During beta phase, generate source maps for better errors
|
||||
new webpack.SourceMapDevToolPlugin({
|
||||
// asset matching
|
||||
test: /\.js?$/,
|
||||
|
||||
// file and reference
|
||||
filename: '[file].map',
|
||||
|
||||
// don't include source file content, since we link to the actual file
|
||||
noSources: true,
|
||||
|
||||
// sourcemap is in 'dist', webpack context is in 'src'
|
||||
moduleFilenameTemplate: info => path.posix.normalize(`../src/${info.resourcePath}`),
|
||||
}),
|
||||
],
|
||||
});
|
Loading…
x
Reference in New Issue
Block a user