From d0c3f7f8b5db6072cb7d001c6bd995c63d82b7b3 Mon Sep 17 00:00:00 2001 From: Aurelsicoko Date: Sat, 11 Nov 2017 22:14:05 +0100 Subject: [PATCH] Avoid to rebuild on path change and override build configuration --- packages/strapi-admin/admin/src/app.js | 29 +++++---- .../strapi-admin/admin/src/public-path.js | 5 ++ .../json/package.json.js | 1 + .../internals/webpack/webpack.base.babel.js | 6 +- .../internals/webpack/webpack.prod.babel.js | 5 +- packages/strapi-helper-plugin/lib/src/app.js | 1 + .../lib/src/public-path.js | 5 ++ .../package.json | 1 + .../package.json | 1 + .../package.json | 1 + packages/strapi/bin/strapi-start.js | 9 ++- packages/strapi/lib/Strapi.js | 4 +- packages/strapi/lib/core/admin.js | 63 +++++++++++++++++++ packages/strapi/lib/core/index.js | 4 +- packages/strapi/lib/middlewares/index.js | 2 +- .../strapi/lib/middlewares/public/index.js | 61 +++++++++++++----- packages/strapi/package.json | 1 + 17 files changed, 161 insertions(+), 38 deletions(-) create mode 100644 packages/strapi-admin/admin/src/public-path.js create mode 100644 packages/strapi-helper-plugin/lib/src/public-path.js create mode 100644 packages/strapi/lib/core/admin.js diff --git a/packages/strapi-admin/admin/src/app.js b/packages/strapi-admin/admin/src/app.js index 96978060ac..54854bd199 100755 --- a/packages/strapi-admin/admin/src/app.js +++ b/packages/strapi-admin/admin/src/app.js @@ -4,6 +4,17 @@ * This is the entry file for the application, only setup and boilerplate * code. */ + +/* eslint-disable */ +// Retrieve remote and backend URLs. +const remoteURL = process.env.REMOTE_URL || 'http://localhost:1337/admin'; +const backendURL = process.env.BACKEND_URL || 'http://localhost:1337'; + +// Retrieve development URL to avoid to re-build. +const devFrontURL = document.getElementsByTagName('body')[0].getAttribute('front'); +const devBackendURL = document.getElementsByTagName('body')[0].getAttribute('back'); + +import './public-path'; import 'babel-polyfill'; // Import all the third party stuff @@ -24,15 +35,12 @@ import { pluginLoaded, updatePlugin } from 'containers/App/actions'; import configureStore from './store'; import { translationMessages, languages } from './i18n'; - -// Retrieve remote and backend URLs. -const remoteURL = process.env.REMOTE_URL || 'http://localhost:1337/admin'; -const backendURL = process.env.BACKEND_URL || 'http://localhost:1337'; +/* eslint-enable */ // Create redux store with history const initialState = {}; const history = createHistory({ - basename: remoteURL.replace(window.location.origin, ''), + basename: (devFrontURL || remoteURL).replace(window.location.origin, ''), }); const store = configureStore(initialState, history); @@ -49,7 +57,6 @@ const render = (translatedMessages) => { ); }; - // Hot reloadable translation json files if (module.hot) { // modules.hot.accept does not accept dynamic dependencies, @@ -74,7 +81,7 @@ window.onload = function onLoad() { // Don't inject plugins in development mode. if (window.location.port !== '4000') { - fetch(`${remoteURL}/config/plugins.json`) + fetch(`${devFrontURL || remoteURL}/config/plugins.json`) .then(response => { return response.json(); }) @@ -140,9 +147,9 @@ const displayNotification = (message, status) => { store.dispatch(showNotification(message, status)); }; -window.strapi = { - remoteURL, - backendURL, +window.strapi = Object.assign(window.strapi || {}, { + remoteURL: devFrontURL || remoteURL, + backendURL: devBackendURL || backendURL, registerPlugin, notification: { success: (message) => { @@ -168,7 +175,7 @@ window.strapi = { }), router: history, languages, -}; +}); const dispatch = store.dispatch; export { diff --git a/packages/strapi-admin/admin/src/public-path.js b/packages/strapi-admin/admin/src/public-path.js new file mode 100644 index 0000000000..bc3778cfe1 --- /dev/null +++ b/packages/strapi-admin/admin/src/public-path.js @@ -0,0 +1,5 @@ +// Retrieve URLs. +const remoteURL = process.env.REMOTE_URL || 'http://localhost:1337/admin'; +const devURL = document.getElementsByTagName('body')[0].getAttribute('front'); + +__webpack_public_path__ = `${(devURL || remoteURL).replace(window.location.origin, '')}/`; diff --git a/packages/strapi-generate-plugin/json/package.json.js b/packages/strapi-generate-plugin/json/package.json.js index 33ae1e59c0..b3dac1dfa8 100755 --- a/packages/strapi-generate-plugin/json/package.json.js +++ b/packages/strapi-generate-plugin/json/package.json.js @@ -30,6 +30,7 @@ module.exports = scope => { 'preanalyze': 'npm run analyze:clean', 'analyze': 'node node_modules/strapi-helper-plugin/lib/internals/scripts/analyze.js', 'prebuild': 'npm run build:clean && npm run test', + 'build:dev': 'cross-env NODE_ENV=development webpack --config node_modules/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js --color -p --progress', 'build': 'cross-env NODE_ENV=production webpack --config node_modules/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js --color -p --progress', 'build:clean': 'rimraf admin/build', 'start': 'cross-env NODE_ENV=development node node_modules/strapi-helper-plugin/lib/server', diff --git a/packages/strapi-helper-plugin/lib/internals/webpack/webpack.base.babel.js b/packages/strapi-helper-plugin/lib/internals/webpack/webpack.base.babel.js index 6eba65397c..fd9568e687 100755 --- a/packages/strapi-helper-plugin/lib/internals/webpack/webpack.base.babel.js +++ b/packages/strapi-helper-plugin/lib/internals/webpack/webpack.base.babel.js @@ -11,7 +11,7 @@ const pkg = require(path.resolve(process.cwd(), 'package.json')); 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, '..', '..'); +const appPath = isAdmin ? path.resolve(process.env.PWD, '..') : path.resolve(process.env.PWD, '..', '..'); try { // Load app' configurations to update `plugins.json` automatically. @@ -24,6 +24,7 @@ try { await strapi.load(); })(); } catch (e) { + console.log(e); throw new Error(`You need to start the WebPack server from the /admin or /plugins/**/admin directories in a Strapi's project.`); } @@ -79,8 +80,7 @@ if (process.env.npm_lifecycle_event === 'start') { module.exports = (options) => ({ entry: options.entry, output: Object.assign({ // Compile into js/build.js - path: path.join(process.cwd(), 'admin', 'build'), - publicPath: '/', + path: path.join(process.cwd(), 'admin', 'build') }, options.output), // Merge with env dependent settings module: { loaders: [{ diff --git a/packages/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js b/packages/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js index 3161d70fc6..58fbc437b7 100755 --- a/packages/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js +++ b/packages/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js @@ -119,14 +119,13 @@ const publicPath = (() => { module.exports = require('./webpack.base.babel')({ // In production, we skip all hot-reloading stuff entry: { - main: appPath + main: appPath, }, // Utilize long-term caching by adding content hashes (not compilation hashes) to compiled assets output: { filename: '[name].js', - chunkFilename: '[name].[chunkhash].chunk.js', - publicPath, + chunkFilename: '[name].[chunkhash].chunk.js' }, // In production, we minify our CSS with cssnano diff --git a/packages/strapi-helper-plugin/lib/src/app.js b/packages/strapi-helper-plugin/lib/src/app.js index 2c30a09924..dbdf7d56fb 100755 --- a/packages/strapi-helper-plugin/lib/src/app.js +++ b/packages/strapi-helper-plugin/lib/src/app.js @@ -4,6 +4,7 @@ * This is the entry file for the application, * only setup and plugin code. */ +import './public-path.js'; // eslint-disabled-line import React from 'react'; import { Provider } from 'react-redux'; diff --git a/packages/strapi-helper-plugin/lib/src/public-path.js b/packages/strapi-helper-plugin/lib/src/public-path.js new file mode 100644 index 0000000000..c1a0644680 --- /dev/null +++ b/packages/strapi-helper-plugin/lib/src/public-path.js @@ -0,0 +1,5 @@ +const pluginPkg = require('../../../../package.json'); +const pluginId = pluginPkg.name.replace(/^strapi-plugin-/i, ''); +const publicPath = `plugins/${pluginId}/`; + +__webpack_public_path__ = `${(strapi.remoteURL).replace(window.location.origin, '')}/${publicPath}`; diff --git a/packages/strapi-plugin-content-manager/package.json b/packages/strapi-plugin-content-manager/package.json index f7ebf15649..34015e43f7 100755 --- a/packages/strapi-plugin-content-manager/package.json +++ b/packages/strapi-plugin-content-manager/package.json @@ -33,6 +33,7 @@ "preanalyze": "npm run analyze:clean", "analyze": "node node_modules/strapi-helper-plugin/lib/internals/scripts/analyze.js", "prebuild": "npm run build:clean && npm run test", + "build:dev": "cross-env NODE_ENV=development webpack --config node_modules/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js --color -p --progress", "build": "cross-env NODE_ENV=production webpack --config node_modules/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js --color -p --progress", "build:clean": "rimraf admin/build", "start": "cross-env NODE_ENV=development PLUGIN=true node node_modules/strapi-helper-plugin/lib/server", diff --git a/packages/strapi-plugin-content-type-builder/package.json b/packages/strapi-plugin-content-type-builder/package.json index ee3c50c17b..d8db061b57 100755 --- a/packages/strapi-plugin-content-type-builder/package.json +++ b/packages/strapi-plugin-content-type-builder/package.json @@ -12,6 +12,7 @@ "preanalyze": "npm run analyze:clean", "analyze": "node node_modules/strapi-helper-plugin/lib/internals/scripts/analyze.js", "prebuild": "npm run build:clean && npm run test", + "build:dev": "cross-env NODE_ENV=development webpack --config node_modules/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js --color -p --progress", "build": "cross-env NODE_ENV=production webpack --config node_modules/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js --color -p --progress", "build:clean": "rimraf admin/build", "start": "cross-env NODE_ENV=development node node_modules/strapi-helper-plugin/lib/server", diff --git a/packages/strapi-plugin-settings-manager/package.json b/packages/strapi-plugin-settings-manager/package.json index 34285c323a..f709a1befc 100755 --- a/packages/strapi-plugin-settings-manager/package.json +++ b/packages/strapi-plugin-settings-manager/package.json @@ -12,6 +12,7 @@ "preanalyze": "npm run analyze:clean", "analyze": "node node_modules/strapi-helper-plugin/lib/internals/scripts/analyze.js", "prebuild": "npm run build:clean && npm run test", + "build:dev": "cross-env NODE_ENV=development webpack --config node_modules/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js --color -p --progress", "build": "cross-env NODE_ENV=production webpack --config node_modules/strapi-helper-plugin/lib/internals/webpack/webpack.prod.babel.js --color -p --progress", "build:clean": "rimraf admin/build", "start": "cross-env NODE_ENV=development node node_modules/strapi-helper-plugin/lib/server", diff --git a/packages/strapi/bin/strapi-start.js b/packages/strapi/bin/strapi-start.js index d2c07561ce..05039b22c8 100755 --- a/packages/strapi/bin/strapi-start.js +++ b/packages/strapi/bin/strapi-start.js @@ -62,7 +62,14 @@ module.exports = function() { const setFilesToWatch = (src) => { var files = fs.readdirSync(src); _.forEach(files, file => { - if (_.startsWith(file, '.') || file === 'node_modules' || file === 'plugins.json') return; + if ( + _.startsWith(file, '.') || + file === 'node_modules' || + file === 'plugins.json' || + file === 'index.html' + ) { + return; + } const filePath = `${src}/${file}`; if (fs.statSync(filePath).isDirectory()) setFilesToWatch(filePath); diff --git a/packages/strapi/lib/Strapi.js b/packages/strapi/lib/Strapi.js index 7773bba332..9527812de6 100755 --- a/packages/strapi/lib/Strapi.js +++ b/packages/strapi/lib/Strapi.js @@ -8,7 +8,7 @@ const path = require('path'); const cluster = require('cluster'); const { includes, get, assign } = require('lodash'); const { logger, models } = require('strapi-utils'); -const { nestedConfigurations, appConfigurations, apis, middlewares, hooks, plugins } = require('./core'); +const { nestedConfigurations, appConfigurations, apis, middlewares, hooks, plugins, admin } = require('./core'); const initializeMiddlewares = require('./middlewares'); const initializeHooks = require('./hooks'); const { EventEmitter } = require('events'); @@ -95,6 +95,8 @@ class Strapi extends EventEmitter { await this.bootstrap(); // Freeze object. await this.freeze(); + // Update source admin. + await admin.call(this); // Launch server. this.server.listen(this.config.port, err => { if (err) { diff --git a/packages/strapi/lib/core/admin.js b/packages/strapi/lib/core/admin.js new file mode 100644 index 0000000000..be3b30e618 --- /dev/null +++ b/packages/strapi/lib/core/admin.js @@ -0,0 +1,63 @@ +'use strict'; + +// Dependencies. +const _ = require('lodash'); +const path = require('path'); +const fs = require('fs'); +const cheerio = require('cheerio') + +module.exports = function() { + return new Promise((resolve, reject) => { + try { + if (this.config.environment === 'test') { + return resolve(); + } + + const sourcePath = path.resolve(this.config.appPath, 'admin', 'admin', 'build', 'index.html'); + + fs.access(path.resolve(this.config.appPath, 'admin', 'admin'), err => { + if (err && err.code !== 'ENOENT') { + return reject(err); + } + + // No admin. + if (err && err.code === 'ENOENT') { + return resolve(); + } + + // Try to access to path. + fs.access(sourcePath, err => { + if (err) { + return reject(err); + } + + fs.readFile(sourcePath, (err, html) => { + const $ = cheerio.load(html.toString()); + + $('script').each(function(i, elem) { + if ($(this).attr('src')) { + const parse = path.parse($(this).attr('src')); + + $(this).attr('src', `${_.get(strapi.config.currentEnvironment.server, 'admin.path', '/admin')}/${parse.base}`); + } + }); + + // Remove previous + $('body').attr('front', `http://${strapi.config.currentEnvironment.server.host}:${strapi.config.currentEnvironment.server.port}${_.get(strapi.config.currentEnvironment.server, 'admin.path', '/admin')}`); + $('body').attr('back', `http://${strapi.config.currentEnvironment.server.host}:${strapi.config.currentEnvironment.server.port}`); + + fs.writeFile(sourcePath, $.html(), (err) => { + if (err) { + return reject(err); + } + + resolve(); + }); + }); + }); + }); + } catch (e) { + reject(e); + } + }); +}; diff --git a/packages/strapi/lib/core/index.js b/packages/strapi/lib/core/index.js index b9d1b77c99..11d2a90f73 100755 --- a/packages/strapi/lib/core/index.js +++ b/packages/strapi/lib/core/index.js @@ -5,6 +5,7 @@ const apis = require('./apis'); const middlewares = require('./middlewares'); const hooks = require('./hooks'); const plugins = require('./plugins'); +const admin = require('./admin'); module.exports = { nestedConfigurations: nested, @@ -12,5 +13,6 @@ module.exports = { apis, middlewares, hooks, - plugins + plugins, + admin }; diff --git a/packages/strapi/lib/middlewares/index.js b/packages/strapi/lib/middlewares/index.js index 07b6241112..b48e18d931 100755 --- a/packages/strapi/lib/middlewares/index.js +++ b/packages/strapi/lib/middlewares/index.js @@ -6,7 +6,7 @@ const { parallel } = require('async'); const { after, includes, indexOf, drop, dropRight, uniq, defaultsDeep, get, set, isEmpty, isUndefined, union, merge } = require('lodash'); module.exports = function() { - const accepted = Object.keys(this.plugins).map(url => `^\/${url}/`).concat(['^\/admin/']); + const accepted = Object.keys(this.plugins).map(url => `^\/${url}/`).concat([`^${get(this.config.currentEnvironment.server, 'admin.path', '/admin')}/`]); // Set if is admin destination for middleware application. // TODO: Use dynamic config for admin url. diff --git a/packages/strapi/lib/middlewares/public/index.js b/packages/strapi/lib/middlewares/public/index.js index d0922f9875..a1368a4ffd 100755 --- a/packages/strapi/lib/middlewares/public/index.js +++ b/packages/strapi/lib/middlewares/public/index.js @@ -110,6 +110,27 @@ module.exports = strapi => { ] }); + // Allow page refresh + strapi.router.route({ + method: 'GET', + path: `${basename}/plugins/*`, + handler: [ + async (ctx, next) => { + const parse = path.parse(ctx.url); + + if (parse.ext === '') { + ctx.url = 'index.html'; + } + + await next(); + }, + strapi.koaMiddlewares.static(`./admin/admin/build`, { + maxage: strapi.config.middleware.settings.public.maxAge, + defer: true + }) + ] + }); + // Serve plugins assets. strapi.router.route({ method: 'GET', @@ -132,23 +153,6 @@ module.exports = strapi => { } }); - // Allow page refresh - strapi.router.route({ - method: 'GET', - path: `${basename}/plugins/*`, - handler: [ - async (ctx, next) => { - ctx.url = 'index.html'; - - await next(); - }, - strapi.koaMiddlewares.static(`./admin/admin/build`, { - maxage: strapi.config.middleware.settings.public.maxAge, - defer: true - }) - ] - }); - // Plugins. _.forEach(strapi.plugins, (value, plugin) => { strapi.router.route({ @@ -173,6 +177,29 @@ module.exports = strapi => { }, ] }); + + strapi.router.route({ + method: 'GET', + path: `${basename}/plugins/${plugin}/*.*`, + handler: [ + async (ctx, next) => { + ctx.url = path.basename(ctx.url); + + // Try to find assets into the build first. + return await strapi.koaMiddlewares.static(`./plugins/${plugin}/admin/build`, { + maxage: strapi.config.middleware.settings.public.maxAge, + defer: true + })(ctx, next); + }, + async (ctx, next) => { + // 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}`, { + maxage: strapi.config.middleware.settings.public.maxAge, + defer: true + })(ctx, next); + }, + ] + }); }); cb(); diff --git a/packages/strapi/package.json b/packages/strapi/package.json index bcd36ed117..e74e9920c1 100755 --- a/packages/strapi/package.json +++ b/packages/strapi/package.json @@ -32,6 +32,7 @@ "dependencies": { "async": "^2.1.2", "boom": "^5.2.0", + "cheerio": "^1.0.0-rc.2", "delegates": "^1.0.0", "glob": "^7.1.2", "kcors": "^2.2.0",