Update build configurations structure and improve DX

This commit is contained in:
Aurelsicoko 2017-11-11 17:22:18 +01:00
parent aeb43d925c
commit d67c64a82a
9 changed files with 118 additions and 111 deletions

View File

@ -9,24 +9,41 @@ const webpack = require('webpack');
const pkg = require(path.resolve(process.cwd(), 'package.json')); const pkg = require(path.resolve(process.cwd(), 'package.json'));
const pluginId = pkg.name.replace(/^strapi-/i, ''); const pluginId = pkg.name.replace(/^strapi-/i, '');
const isAdmin = process.env.IS_ADMIN === 'true';
const appPath = isAdmin ? path.resolve(process.env.PWD, '..'): path.resolve(process.env.PWD, '..', '..');
try {
// Load app' configurations to update `plugins.json` automatically.
const strapi = require(path.join(appPath, 'node_modules', 'strapi'));
strapi.config.appPath = appPath;
strapi.log.level = 'silent';
(async () => {
await strapi.load();
})();
} catch (e) {
throw new Error(`You need to start the WebPack server from the /admin or /plugins/**/admin directories in a Strapi's project.`);
}
// Define remote and backend URLs. // Define remote and backend URLs.
const URLs = { const URLs = {
remote: null, host: null,
backend: null backend: null
}; };
if (process.env.IS_ADMIN === 'true') { if (isAdmin) {
// Load server configuration. // Load server configuration.
const serverConfig = path.resolve(process.env.PWD, '..', 'config', 'environments', _.lowerCase(process.env.NODE_ENV), 'server.json'); const serverConfig = path.resolve(process.env.PWD, '..', 'config', 'environments', _.lowerCase(process.env.NODE_ENV), 'server.json');
try { try {
const server = require(serverConfig); const server = require(serverConfig);
const folder = _.get(server, 'admin.folder') ? server.admin.folder : '/admin'; const path = _.get(server, 'admin.path', '/admin');
if (process.env.PWD.indexOf(folder) !== -1) { if (process.env.PWD.indexOf('/admin') !== -1) {
URLs.remote = _.get(server, 'admin.remoteURL', null) ? _.get(server, 'admin.remoteURL', null) : `http://${_.get(server, 'host', 'localhost')}:${_.get(server, 'port', 1337)}${folder}`; URLs.host = _.get(server, 'admin.build.host', `http://${_.get(server, 'host', 'localhost')}:${_.get(server, 'port', 1337)}${path}`);
URLs.backend = _.get(server, 'admin.backendURL', null) ? _.get(server, 'admin.backendURL', null) : `http://${_.get(server, 'host', 'localhost')}:${_.get(server, 'port', 1337)}`; URLs.backend = _.get(server, 'admin.build.backend', `http://${_.get(server, 'host', 'localhost')}:${_.get(server, 'port', 1337)}`);
} }
} catch (e) { } catch (e) {
throw new Error(`Impossible to access to ${serverConfig}`) throw new Error(`Impossible to access to ${serverConfig}`)
@ -44,18 +61,12 @@ if (process.env.npm_lifecycle_event === 'start') {
try { try {
fs.accessSync(path.resolve(process.env.PWD, '..', 'plugins'), fs.constants.R_OK); fs.accessSync(path.resolve(process.env.PWD, '..', 'plugins'), fs.constants.R_OK);
} catch (e) { } catch (e) {
try {
fs.accessSync(path.resolve(process.env.PWD, '..', 'api'), fs.constants.R_OK);
// Allow app without plugins. // Allow app without plugins.
plugins.exist = true; plugins.exist = true;
} catch (e) {
throw new Error(`You need to start the WebPack server from the /admin directory in a Strapi's project.`);
}
} }
// Read `plugins` directory. // Read `plugins` directory.
plugins.src = process.env.IS_ADMIN === 'true' && !plugins.exist ? fs.readdirSync(path.resolve(process.env.PWD, '..', 'plugins')).filter(x => x[0] !== '.') : []; plugins.src = isAdmin && !plugins.exist ? fs.readdirSync(path.resolve(process.env.PWD, '..', 'plugins')).filter(x => x[0] !== '.') : [];
// Construct object of plugin' paths. // Construct object of plugin' paths.
plugins.folders = plugins.src.reduce((acc, current) => { plugins.folders = plugins.src.reduce((acc, current) => {
@ -189,7 +200,7 @@ module.exports = (options) => ({
new webpack.DefinePlugin({ new webpack.DefinePlugin({
'process.env': { 'process.env': {
NODE_ENV: JSON.stringify(process.env.NODE_ENV), NODE_ENV: JSON.stringify(process.env.NODE_ENV),
REMOTE_URL: JSON.stringify(URLs.remote), REMOTE_URL: JSON.stringify(URLs.host),
BACKEND_URL: JSON.stringify(URLs.backend), BACKEND_URL: JSON.stringify(URLs.backend),
}, },
}), }),

View File

@ -14,28 +14,24 @@ const postcssReporter = require('postcss-reporter');
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
const LodashModuleReplacementPlugin = require('lodash-webpack-plugin'); const LodashModuleReplacementPlugin = require('lodash-webpack-plugin');
let noPlugin = false; // Load plugins into the same build in development mode.
let plugins = []; const plugins = {
let pluginFolders = {}; exist: false,
src: [],
folders: {}
};
if (process.env.npm_lifecycle_event === 'start') { if (process.env.npm_lifecycle_event === 'start') {
try { try {
fs.accessSync(path.resolve(process.env.PWD, '..', 'plugins'), fs.constants.R_OK); fs.accessSync(path.resolve(process.env.PWD, '..', 'plugins'), fs.constants.R_OK);
} catch (e) { } catch (e) {
try {
fs.accessSync(path.resolve(process.env.PWD, '..', 'api'), fs.constants.R_OK);
// Allow app without plugins. // Allow app without plugins.
noPlugin = true; plugins.exist = true;
} catch (e) {
throw new Error(`You need to start the WebPack server from the /admin directory in a Strapi's project.`);
}
} }
plugins = process.env.IS_ADMIN === 'true' && !noPlugin ? fs.readdirSync(path.resolve(process.env.PWD, '..', 'plugins')) plugins.src = process.env.IS_ADMIN === 'true' && !plugins.exist ? fs.readdirSync(path.resolve(process.env.PWD, '..', 'plugins')).filter(x => x[0] !== '.') : [];
.filter(x => x[0] !== '.') : [];
pluginFolders = plugins.reduce((acc, current) => { plugins.folders = plugins.reduce((acc, current) => {
acc[current] = path.resolve(process.env.PWD, '..', 'plugins', current, 'node_modules', 'strapi-helper-plugin', 'lib', 'src'); acc[current] = path.resolve(process.env.PWD, '..', 'plugins', current, 'node_modules', 'strapi-helper-plugin', 'lib', 'src');
return acc; return acc;
@ -52,8 +48,8 @@ module.exports = require('./webpack.base.babel')({
`webpack-hot-middleware/client?path=http://localhost:${port}/__webpack_hmr`, `webpack-hot-middleware/client?path=http://localhost:${port}/__webpack_hmr`,
appPath, appPath,
] ]
}, plugins.reduce((acc, current) => { }, plugins.src.reduce((acc, current) => {
acc[current] = path.resolve(pluginFolders[current], 'app.js'); acc[current] = path.resolve(plugins.folders[current], 'app.js');
return acc; return acc;
}, {}) }, {})

View File

@ -46,25 +46,26 @@ const plugins = [
// new BundleAnalyzerPlugin(), // new BundleAnalyzerPlugin(),
]; ];
let folder = 'admin'; // Load server configuration.
let remoteURL = undefined; const serverConfig = isAdmin ?
path.resolve(process.env.PWD, '..', 'config', 'environments', _.lowerCase(process.env.NODE_ENV), 'server.json'):
path.resolve(process.env.PWD, '..', '..', 'config', 'environments', _.lowerCase(process.env.NODE_ENV), 'server.json');
const server = require(serverConfig);
const settings = {
path: 'admin',
folder: 'plugins',
host: _.get(server, 'admin.build.host')
};
// Build the `index.html file` // Build the `index.html file`
if (isAdmin) { if (isAdmin) {
// Load server configuration. settings.path = _.get(server, 'admin.path', 'admin');
const serverConfig = path.resolve(process.env.PWD, '..', 'config', 'environments', _.lowerCase(process.env.NODE_ENV), 'server.json'); settings.folder = _.get(server, 'admin.build.plugins.folder', 'plugins');
const server = require(serverConfig);
if (_.get(server, 'admin.remoteURL')) { if (settings.path[0] === '/') {
remoteURL = server.admin.remoteURL; settings.path = settings.path.substring(1);
}
folder = _.get(server, 'admin.folder') ?
server.admin.folder :
'admin';
if (folder[0] === '/') {
folder = folder.substring(1);
} }
plugins.push(new HtmlWebpackPlugin({ plugins.push(new HtmlWebpackPlugin({
@ -103,14 +104,16 @@ const appPath = isAdmin
const publicPath = (() => { const publicPath = (() => {
if (isAdmin) { if (isAdmin) {
if (remoteURL) { if (settings.host) {
return `${remoteURL}/`; return `${settings.host}/`;
} }
return `/${folder}/`; return `/${settings.path}/`;
} }
return `/${pluginId}/assets/`; return settings.host ?
`${settings.host}/${settings.folder}/${pluginId}/`:
`/${settings.folder}/${pluginId}/`;
})(); })();
module.exports = require('./webpack.base.babel')({ module.exports = require('./webpack.base.babel')({

View File

@ -8,7 +8,9 @@ module.exports = function() {
return Promise.all([ return Promise.all([
new Promise((resolve, reject) => { new Promise((resolve, reject) => {
// Load configurations. // Load configurations.
glob('./api/*/!(config)/*.*(js|json)', {}, (err, files) => { glob('./api/*/!(config)/*.*(js|json)', {
cwd: this.config.appPath
}, (err, files) => {
if (err) { if (err) {
return reject(err); return reject(err);
} }
@ -20,7 +22,9 @@ module.exports = function() {
}), }),
new Promise((resolve, reject) => { new Promise((resolve, reject) => {
// Load configurations. // Load configurations.
glob('./admin/!(config|node_modules)/*.*(js|json)', {}, (err, files) => { glob('./admin/!(config|node_modules)/*.*(js|json)', {
cwd: this.config.appPath
}, (err, files) => {
if (err) { if (err) {
return reject(err); return reject(err);
} }
@ -32,7 +36,9 @@ module.exports = function() {
}), }),
new Promise((resolve, reject) => { new Promise((resolve, reject) => {
// Load configurations. // Load configurations.
glob('./plugins/*/!(config|node_modules)/*.*(js|json)', {}, (err, files) => { glob('./plugins/*/!(config|node_modules)/*.*(js|json)', {
cwd: this.config.appPath
}, (err, files) => {
if (err) { if (err) {
return reject(err); return reject(err);
} }

View File

@ -10,7 +10,9 @@ module.exports.nested = function() {
return Promise.all([ return Promise.all([
// Load root configurations. // Load root configurations.
new Promise((resolve, reject) => { new Promise((resolve, reject) => {
glob('./config/**/*.*(js|json)', {}, (err, files) => { glob('./config/**/*.*(js|json)', {
cwd: this.config.appPath
}, (err, files) => {
if (err) { if (err) {
return reject(err); return reject(err);
} }
@ -20,7 +22,9 @@ module.exports.nested = function() {
}), }),
// Load APIs configurations. // Load APIs configurations.
new Promise((resolve, reject) => { new Promise((resolve, reject) => {
glob('./api/*/config/**/*.*(js|json)', {}, (err, files) => { glob('./api/*/config/**/*.*(js|json)', {
cwd: this.config.appPath
}, (err, files) => {
if (err) { if (err) {
return reject(err); return reject(err);
} }
@ -30,7 +34,9 @@ module.exports.nested = function() {
}), }),
// Load plugins configurations. // Load plugins configurations.
new Promise((resolve, reject) => { new Promise((resolve, reject) => {
glob('./plugins/*/config/**/*.*(js|json)', {}, (err, files) => { glob('./plugins/*/config/**/*.*(js|json)', {
cwd: this.config.appPath
}, (err, files) => {
if (err) { if (err) {
return reject(err); return reject(err);
} }
@ -40,7 +46,9 @@ module.exports.nested = function() {
}), }),
// Load admin configurations. // Load admin configurations.
new Promise((resolve, reject) => { new Promise((resolve, reject) => {
glob('./admin/config/**/*.*(js|json)', {}, (err, files) => { glob('./admin/config/**/*.*(js|json)', {
cwd: this.config.appPath
}, (err, files) => {
if (err) { if (err) {
return reject(err); return reject(err);
} }

View File

@ -38,7 +38,7 @@ module.exports = function() {
// Load configurations. // Load configurations.
glob('./*', { glob('./*', {
cwd: path.resolve(process.cwd(), 'hooks') cwd: path.resolve(this.config.appPath, 'hooks')
}, (err, files) => { }, (err, files) => {
if (err) { if (err) {
return reject(err); return reject(err);

View File

@ -30,7 +30,7 @@ module.exports = function() {
); );
}), }),
new Promise((resolve, reject) => { new Promise((resolve, reject) => {
const cwd = process.cwd(); const cwd = this.config.appPath;
glob( glob(
'./node_modules/*(koa-*|kcors)', './node_modules/*(koa-*|kcors)',
@ -47,7 +47,7 @@ module.exports = function() {
); );
}), }),
new Promise((resolve, reject) => { new Promise((resolve, reject) => {
const cwd = process.cwd(); const cwd = this.config.appPath;
glob( glob(
'./node_modules/*(strapi-middleware-*)', './node_modules/*(strapi-middleware-*)',
@ -81,7 +81,7 @@ module.exports = function() {
); );
}), }),
new Promise((resolve, reject) => { new Promise((resolve, reject) => {
const cwd = path.resolve(process.cwd(), 'middlewares'); const cwd = path.resolve(this.config.appPath, 'middlewares');
glob( glob(
'./*', './*',

View File

@ -7,35 +7,27 @@ const fs = require('fs');
module.exports = function() { module.exports = function() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const folder = (() => { const folder = ((url = _.get(strapi.config.currentEnvironment.server, 'admin.path', 'admin')) =>
if (_.get(strapi.config.currentEnvironment.server, 'admin.folder')) { url[0] === '/' ? url.substring(1) : url
// Relative URL )();
if (strapi.config.currentEnvironment.server.admin.folder[0] === '/') {
return strapi.config.currentEnvironment.server.admin.folder.substring(1);
}
return strapi.config.currentEnvironment.server.admin.folder;
}
return 'admin';
})();
const configuratePlugin = (acc, current, source, x) => { const configuratePlugin = (acc, current, source, x) => {
switch (source) { switch (source) {
case 'remote': case 'host': {
if (!_.get(this.config.environments[current].server, 'admin.remoteURL')) { if (!_.get(this.config.environments[current].server, 'admin.build.host')) {
throw new Error(`You can't use \`remote\` as a source without set the \`remoteURL\` configuration.`); throw new Error(`You can't use \`remote\` as a source without set the \`host\` configuration.`);
} }
const subFolder = _.get(this.config.environments[current].server, 'admin.plugins.subFolder', null); const folder = _.get(this.config.environments[current].server, 'admin.build.plugins.folder', null);
if (_.isString(subFolder)) { if (_.isString(folder)) {
const cleanSubFolder = subFolder[0] === '/' ? subFolder.substring(1) : subFolder; const cleanFolder = folder[0] === '/' ? folder.substring(1) : folder;
return `${this.config.environments[current].server.admin.remoteURL}/${cleanSubFolder}/${x}/main.js`; return `${this.config.environments[current].server.admin.build.host}/${cleanFolder}/${x}/main.js`;
} }
return `${this.config.environments[current].server.admin.remoteURL}/${x}/main.js`; return `${this.config.environments[current].server.admin.build.host}/${x}/main.js`;
}
case 'custom': case 'custom':
if (!_.isEmpty(_.get(this.plugins[x].config, `sources.${current}`, {}))) { if (!_.isEmpty(_.get(this.plugins[x].config, `sources.${current}`, {}))) {
return acc[current] = this.plugins[x].config.sources[current]; return acc[current] = this.plugins[x].config.sources[current];
@ -49,14 +41,14 @@ module.exports = function() {
}; };
const sourcePath = process.env.NODE_ENV !== 'test' ? const sourcePath = process.env.NODE_ENV !== 'test' ?
path.resolve(this.config.appPath, folder, 'admin', 'src', 'config', 'plugins.json'): path.resolve(this.config.appPath, 'admin', 'admin', 'src', 'config', 'plugins.json'):
path.resolve(this.config.appPath, 'packages', 'strapi-admin', 'admin', 'src', 'config', 'plugins.json'); path.resolve(this.config.appPath, 'packages', 'strapi-admin', 'admin', 'src', 'config', 'plugins.json');
const buildPath = process.env.NODE_ENV !== 'test' ? const buildPath = process.env.NODE_ENV !== 'test' ?
path.resolve(this.config.appPath, folder, 'admin', 'build', 'config', 'plugins.json'): path.resolve(this.config.appPath, 'admin', 'admin', 'build', 'config', 'plugins.json'):
path.resolve(this.config.appPath, 'packages', 'strapi-admin', 'admin', 'build', 'config', 'plugins.json'); path.resolve(this.config.appPath, 'packages', 'strapi-admin', 'admin', 'build', 'config', 'plugins.json');
try { try {
fs.access(path.resolve(this.config.appPath, folder, 'admin'), err => { fs.access(path.resolve(this.config.appPath, 'admin', 'admin'), err => {
if (err && err.code !== 'ENOENT') { if (err && err.code !== 'ENOENT') {
return reject(err); return reject(err);
} }
@ -96,7 +88,7 @@ module.exports = function() {
const data = Object.keys(this.plugins).map(x => ({ const data = Object.keys(this.plugins).map(x => ({
id: x, id: x,
source: Object.keys(this.config.environments).reduce((acc, current) => { source: Object.keys(this.config.environments).reduce((acc, current) => {
const source = _.get(this.config.environments[current].server, 'admin.plugins.source', 'origin'); const source = _.get(this.config.environments[current].server, 'admin.build.plugins.source', 'origin');
if (_.isString(source)) { if (_.isString(source)) {
acc[current] = configuratePlugin(acc, current, source, x); acc[current] = configuratePlugin(acc, current, source, x);

View File

@ -72,8 +72,8 @@ module.exports = strapi => {
] ]
}); });
const basename = _.get(strapi.config.currentEnvironment.server, 'admin.folder') ? const basename = _.get(strapi.config.currentEnvironment.server, 'admin.path') ?
strapi.config.currentEnvironment.server.admin.folder : strapi.config.currentEnvironment.server.admin.path :
'/admin'; '/admin';
// Serve /admin index page. // Serve /admin index page.
@ -86,7 +86,7 @@ module.exports = strapi => {
await next(); await next();
}, },
strapi.koaMiddlewares.static(`.${basename}/admin/build`, { strapi.koaMiddlewares.static(`./admin/admin/build`, {
maxage: strapi.config.middleware.settings.public.maxAge, maxage: strapi.config.middleware.settings.public.maxAge,
defer: true defer: true
}) })
@ -103,7 +103,7 @@ module.exports = strapi => {
await next(); await next();
}, },
strapi.koaMiddlewares.static(`.${basename}/admin/build`, { strapi.koaMiddlewares.static(`./admin/admin/build`, {
maxage: strapi.config.middleware.settings.public.maxAge, maxage: strapi.config.middleware.settings.public.maxAge,
defer: true defer: true
}) })
@ -125,7 +125,7 @@ module.exports = strapi => {
} }
// Handle subfolders. // Handle subfolders.
return await strapi.koaMiddlewares.static(`.${basename}/admin/build/${ctx.params.resource}`, { return await strapi.koaMiddlewares.static(`./admin/admin/build/${ctx.params.resource}`, {
maxage: strapi.config.middleware.settings.public.maxAge, maxage: strapi.config.middleware.settings.public.maxAge,
defer: true defer: true
})(ctx, next); })(ctx, next);
@ -142,7 +142,7 @@ module.exports = strapi => {
await next(); await next();
}, },
strapi.koaMiddlewares.static(`.${basename}/admin/build`, { strapi.koaMiddlewares.static(`./admin/admin/build`, {
maxage: strapi.config.middleware.settings.public.maxAge, maxage: strapi.config.middleware.settings.public.maxAge,
defer: true defer: true
}) })
@ -158,28 +158,19 @@ module.exports = strapi => {
async (ctx, next) => { async (ctx, next) => {
ctx.url = path.basename(ctx.url); ctx.url = path.basename(ctx.url);
await next(); // Try to find assets into the build first.
}, return await strapi.koaMiddlewares.static(`./plugins/${plugin}/admin/build`, {
strapi.koaMiddlewares.static(`./plugins/${plugin}/${strapi.config.middleware.settings.public.path || strapi.config.paths.static}`, {
maxage: strapi.config.middleware.settings.public.maxAge, maxage: strapi.config.middleware.settings.public.maxAge,
defer: true defer: true
}) })(ctx, next);
] },
});
strapi.router.route({
method: 'GET',
path: `/${plugin}/assets/*.*`,
handler: [
async (ctx, next) => { async (ctx, next) => {
ctx.url = path.basename(ctx.url); // Try to find assets in the source then.
return await strapi.koaMiddlewares.static(`./plugins/${plugin}/${strapi.config.middleware.settings.public.path || strapi.config.paths.static}`, {
await next();
},
strapi.koaMiddlewares.static(`./plugins/${plugin}/admin/build`, {
maxage: strapi.config.middleware.settings.public.maxAge, maxage: strapi.config.middleware.settings.public.maxAge,
defer: true defer: true
}) })(ctx, next);
},
] ]
}); });
}); });