optimization

This commit is contained in:
Alexandre Bodin 2019-04-30 14:47:49 +02:00
parent 735a349736
commit c8b17ff752
14 changed files with 235 additions and 987 deletions

View File

@ -129,27 +129,7 @@ async function build({ dir, env, options }) {
warnings: messages.warnings,
});
});
})
.then(
({ stats, warnings }) => {
console.log(chalk.green('Compiled successfully.\n'));
},
err => {
console.log(chalk.red('Failed to compile.\n'));
const message = err != null && err.message;
console.log((message || err) + '\n');
console.log();
process.exit(1);
}
)
.catch(err => {
if (err && err.message) {
console.log(err.message);
}
process.exit(1);
});
});
}
module.exports = {

View File

@ -72,7 +72,6 @@
"sanitize.css": "^4.1.0",
"sass-loader": "^7.1.0",
"shelljs": "^0.7.8",
"simple-progress-webpack-plugin": "^1.1.2",
"strapi-helper-plugin": "^3.0.0-beta.0",
"strapi-utils": "^3.0.0-beta.0",
"style-loader": "^0.23.1",
@ -80,9 +79,7 @@
"terser-webpack-plugin": "^1.2.3",
"url-loader": "^1.1.2",
"video-react": "^0.13.2",
"webpack": "^4.29.6",
"webpack-cli": "^3.3.0",
"webpack-dev-server": "^3.3.1"
"webpack": "^4.29.6"
},
"author": {
"name": "Strapi",

View File

@ -3,7 +3,6 @@ const webpack = require('webpack');
// Webpack plugins
const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');
const SimpleProgressWebpackPlugin = require('simple-progress-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const DuplicatePckgChecker = require('duplicate-package-checker-webpack-plugin');
@ -242,8 +241,6 @@ module.exports = ({
template: path.resolve(__dirname, 'index.html'),
favicon: path.resolve(__dirname, 'admin/src/favicon.ico'),
}),
new SimpleProgressWebpackPlugin(),
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify(
isProduction ? 'production' : 'development'

View File

@ -20,7 +20,7 @@ const runInstall = () => {
if (packageManager.isStrapiInstalledWithNPM()) {
return new Promise((resolve, reject) => {
shell.exec(
'npm install',
'npm install --production --no-optional',
{ silent: true },
(code, _, stderr) => {
if (stderr && code !== 0) return reject(new Error(stderr));
@ -32,7 +32,7 @@ const runInstall = () => {
return new Promise((resolve, reject) => {
shell.exec(
'yarn install',
'yarn install --production --no-optional',
{ silent: true },
(code, _, stderr) => {
if (stderr && code !== 0) return reject(new Error(stderr));
@ -74,6 +74,12 @@ module.exports = async (scope, cb) => {
trackSuccess('didCreateProject', scope);
loader.start('Building the admin UI');
shell.exec('npm run build');
loader.succeed();
if (scope.quick) {
console.log('⚡️ Starting your application...');
} else {

View File

@ -19,8 +19,6 @@ function BlockerComponent({
blockerComponentContent = '',
}) {
let content;
console.log(blockerComponentContent);
switch (blockerComponentContent) {
case 'renderIde':
content = renderIde();

View File

@ -146,12 +146,8 @@ program
program
.command('build [dir]')
.option('--env [env]', 'Build for which env')
.description('Builds the strapi admin app')
.action((dir, options) => {
const env = options.env || 'production';
getScript('build')({ dir, env });
});
.action(dir => getScript('build')({ dir }));
/**
* Normalize help argument

View File

@ -119,14 +119,15 @@ class Strapi extends EventEmitter {
try {
// Emit starting event.
this.emit('server:starting');
// Load the app.
await this.load();
// Run bootstrap function.
await this.runBootstrapFunctions();
// Freeze object.
await this.freeze();
// Init first start
utils.init.call(this);
utils.init(this.config);
// Launch server.
this.server.listen(this.config.port, async err => {
if (err) return this.stopWithError(err);
@ -232,7 +233,6 @@ class Strapi extends EventEmitter {
process.exit(1);
}
// TODO: Split code
async load() {
await this.enhancer();

View File

@ -1,13 +1,14 @@
'use strict';
const path = require('path');
const _ = require('lodash');
const { green } = require('chalk');
const strapiAdmin = require('strapi-admin');
const { cli } = require('strapi-utils');
const strapi = require('../index');
process.env.NODE_ENV = 'production';
// build script shoul only run in production mode
module.exports = ({ dir = '', env }) => {
module.exports = ({ dir = '' }) => {
// Check that we're in a valid Strapi project.
if (!cli.isStrapiApp()) {
return console.log(
@ -17,19 +18,40 @@ module.exports = ({ dir = '', env }) => {
const appPath = path.join(process.cwd(), dir);
console.log(`Building your app with ${green(env)} configuration`);
const app = strapi({ appPath });
// Require server configurations
const server = require(path.resolve(
appPath,
'config',
'environments',
env,
'server.json'
));
// prepare the app => load the configurations
return app
.load()
.then(() => {
console.log(
`Building your app with ${green(
app.config.environment
)} configuration ...`
);
return strapiAdmin.build({
dir: process.cwd(),
env: 'production',
});
const adminPath = _.get(
app.config.currentEnvironment.server,
'admin.path',
'admin'
);
return strapiAdmin.build({
dir: process.cwd(),
// front end build env is always production for now
env: 'production',
options: {
backend: app.config.url,
publicPath: path.join('/', adminPath, '/'),
},
});
})
.then(() => {
console.log('Compilation successfull');
process.exit();
})
.catch(err => {
console.log('Compilation failed');
console.error(err);
});
};

View File

@ -14,7 +14,7 @@ const strapi = require('../strapi');
// Public dependencies
const _ = require('lodash');
const fs = require('fs-extra');
const { cyan } = require('chalk');
const { cyan, green } = require('chalk');
const chokidar = require('chokidar');
const strapiAdmin = require('strapi-admin');
@ -22,15 +22,13 @@ const strapiAdmin = require('strapi-admin');
const { cli, logger } = require('strapi-utils');
/**
* `$ strapi start`
* `$ strapi dev`
*
* Expose method which starts the appropriate instance of Strapi
* (fire up the application in our working directory).
*/
module.exports = async function(dir = '.') {
process.env.NODE_ENV = 'development';
module.exports = async function(dir = '') {
// Check that we're in a valid Strapi project.
if (!cli.isStrapiApp()) {
return console.log(
@ -40,27 +38,27 @@ module.exports = async function(dir = '.') {
const appPath = path.join(process.cwd(), dir);
// Require server configurations
const server = require(path.resolve(
appPath,
'config',
'environments',
'development',
'server.json'
));
if (!fs.existsSync(path.resolve(appPath, 'build'))) {
await strapiAdmin.build({
dir: process.cwd(),
env: 'production',
});
} else {
}
try {
const strapiInstance = strapi({ appPath });
if (_.get(server, 'autoReload.enabled') === true) {
// Set NODE_ENV
if (_.isEmpty(process.env.NODE_ENV)) {
process.env.NODE_ENV = 'development';
}
// Require server configurations
const server = require(path.resolve(
appPath,
'config',
'environments',
'development',
'server.json'
));
if (
process.env.NODE_ENV === 'development' &&
_.get(server, 'autoReload.enabled') === true
) {
if (cluster.isMaster) {
cluster.on('message', (worker, message) => {
switch (message) {

View File

@ -1,10 +1,9 @@
'use strict';
const path = require('path');
const _ = require('lodash');
const fs = require('fs-extra');
const { createController, createService } = require('../core-api');
const getURLFromSegments = require('../utils/url-from-segments');
module.exports = function(strapi) {
// Retrieve Strapi version.
@ -120,7 +119,6 @@ module.exports = function(strapi) {
});
});
strapi.admin.queries = (model, plugin) => {
return strapi.query(model, plugin, strapi.admin.config.queries);
};
@ -398,12 +396,3 @@ const enableHookNestedDependencies = function(
}
}
};
const getURLFromSegments = function({ hostname, port, ssl = false }) {
const protocol = ssl ? 'https' : 'http';
const defaultPort = ssl ? 443 : 80;
const portString =
port === undefined || parseInt(port) === defaultPort ? '' : `:${port}`;
return `${protocol}://${hostname}${portString}`;
};

View File

@ -0,0 +1,46 @@
const getUrlFromSegments = require('../url-from-segments');
describe('getUrlFromSegments', () => {
test('Handles hostname', () => {
expect(getUrlFromSegments({ hostname: 'localhost' })).toEqual(
'http://localhost'
);
expect(getUrlFromSegments({ hostname: 'otherhost.com' })).toEqual(
'http://otherhost.com'
);
});
test('Handles port', () => {
expect(getUrlFromSegments({ hostname: 'localhost', port: '80' })).toEqual(
'http://localhost'
);
expect(getUrlFromSegments({ hostname: 'localhost', port: '8000' })).toEqual(
'http://localhost:8000'
);
expect(
getUrlFromSegments({ hostname: 'otherhost.com', port: 5421 })
).toEqual('http://otherhost.com:5421');
});
test('Handles ssl and ports', () => {
expect(getUrlFromSegments({ hostname: 'localhost', ssl: true })).toEqual(
'https://localhost'
);
expect(
getUrlFromSegments({ hostname: 'localhost', ssl: true, port: 532 })
).toEqual('https://localhost:532');
expect(
getUrlFromSegments({ hostname: 'localhost', ssl: true, port: 443 })
).toEqual('https://localhost');
expect(
getUrlFromSegments({ hostname: 'otherhost.com', ssl: true })
).toEqual('https://otherhost.com');
expect(
getUrlFromSegments({ hostname: 'otherhost.com', ssl: true, port: 7263 })
).toEqual('https://otherhost.com:7263');
});
});

View File

@ -7,8 +7,15 @@
const fs = require('fs');
const path = require('path');
const { map } = require('async'); // eslint-disable-line import/order
const { setWith, merge, get, difference, intersection, isObject, isFunction } = require('lodash');
const os = require('os');
const {
setWith,
merge,
get,
difference,
intersection,
isObject,
isFunction,
} = require('lodash');
const vm = require('vm');
const fetch = require('node-fetch');
const Buffer = require('buffer').Buffer;
@ -17,138 +24,46 @@ const exposer = require('./exposer');
const openBrowser = require('./openBrowser');
module.exports = {
init: function() {
if (this.config.init) {
fs.unlinkSync(path.resolve(this.config.appPath, 'config', '.init.json'));
init(config) {
if (config.init) {
fs.unlinkSync(path.resolve(config.appPath, 'config', '.init.json'));
}
},
loadFile: function(url) {
// Clear cache.
delete require.cache[require.resolve(path.resolve(this.config.appPath, url))];
// Require without cache.
return require(path.resolve(this.config.appPath, url));
},
setConfig: function(ctx, path, type, loader) {
const objPath = type === 'optional'
? this.optionalPath(path)
: this.aggregatePath(path);
// Load value.
const value = loader(path);
// Merge doesn't work for none-object value and function.
const obj = isObject(value) && !isFunction(value) ? merge(get(ctx, objPath), value) : value;
// Assignation.
return setWith(ctx, objPath, obj, Object);
},
setConfigAdmin: function(ctx, path, type, loader) {
const objPath = 'admin.' + (type === 'optional'
? this.optionalPath(path)
: this.aggregatePath(path));
// Direct assignation.
if (objPath.split('.').length === 1) {
return setWith(
ctx,
objPath,
merge(get(ctx, objPath), loader(path)),
Object
);
}
// Nested assignation.
return setWith(ctx, objPath, loader(path), Object);
},
optionalPath: path => {
return path
.replace(/(\.settings|.json|.js)/g, '')
.split('/')
.slice(1, path.split('/').length - 1)
.join('.')
.toLowerCase();
},
aggregatePath: path => {
return path
.replace(/(\.settings|.json|.js)/g, '')
.split('/')
.slice(1)
.join('.')
.toLowerCase();
},
loadConfig: function(files, shouldBeAggregated = false) {
const aggregate = files.filter(p => {
if (shouldBeAggregated) {
return true;
}
if (intersection(p.split('/').map(p => p.replace('.json', '')), ['environments', 'database', 'security', 'request', 'response', 'server']).length === 2) {
return true;
}
if (
p.indexOf('config/functions') !== -1 ||
p.indexOf('config/policies') !== -1 ||
p.indexOf('config/locales') !== -1 ||
p.indexOf('config/hook') !== -1 ||
p.indexOf('config/middleware') !== -1 ||
p.indexOf('config/language') !== -1 ||
p.indexOf('config/queries') !== -1 ||
p.indexOf('config/layout') !== -1
) {
return true;
}
return false;
});
const optional = difference(files, aggregate);
return Promise.all([
new Promise((resolve, reject) => {
map(aggregate, p =>
module.exports.setConfig(this, p, 'aggregate', this.loadFile)
);
resolve();
}),
new Promise((resolve, reject) => {
map(optional, p =>
module.exports.setConfig(this, p, 'optional', this.loadFile)
);
resolve();
})
]);
},
usage: async function () {
usage: async function() {
try {
if (this.config.uuid) {
const publicKey = fs.readFileSync(path.resolve(__dirname, 'resources', 'key.pub'));
const publicKey = fs.readFileSync(
path.resolve(__dirname, 'resources', 'key.pub')
);
const options = { timeout: 1500 };
const [usage, signedHash, required] = await Promise.all([
fetch('https://strapi.io/assets/images/usage.gif', options),
fetch('https://strapi.io/hash.txt', options),
fetch('https://strapi.io/required.txt', options)
fetch('https://strapi.io/required.txt', options),
]).catch(err => {});
if (usage.status === 200 && signedHash.status === 200) {
const code = Buffer.from(await usage.text(), 'base64').toString();
const hash = crypto.createHash('sha512').update(code).digest('hex');
const dependencies = Buffer.from(await required.text(), 'base64').toString();
const hash = crypto
.createHash('sha512')
.update(code)
.digest('hex');
const dependencies = Buffer.from(
await required.text(),
'base64'
).toString();
const verifier = crypto.createVerify('RSA-SHA256').update(hash);
if (verifier.verify(publicKey, await signedHash.text(), 'hex')) {
return new Promise(resolve => {
vm.runInNewContext(code)(this.config.uuid, exposer(dependencies), resolve);
vm.runInNewContext(code)(
this.config.uuid,
exposer(dependencies),
resolve
);
});
}
}
@ -157,5 +72,5 @@ module.exports = {
// Silent.
}
},
openBrowser
openBrowser,
};

View File

@ -0,0 +1,13 @@
'use strict';
/**
* Returns a url base on hostname, port and ssl options
*/
module.exports = ({ hostname, port, ssl = false }) => {
const protocol = ssl ? 'https' : 'http';
const defaultPort = ssl ? 443 : 80;
const portString =
port === undefined || parseInt(port, 10) === defaultPort ? '' : `:${port}`;
return `${protocol}://${hostname}${portString}`;
};

853
yarn.lock

File diff suppressed because it is too large Load Diff