Skip to content

Commit

Permalink
adds static asset support #518
Browse files Browse the repository at this point in the history
  • Loading branch information
delambo committed Aug 4, 2017
1 parent 07eda00 commit 9150e93
Show file tree
Hide file tree
Showing 22 changed files with 286 additions and 204 deletions.
Empty file.
4 changes: 4 additions & 0 deletions e2e_tests/fixtures/build-default/src/client/index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@

import '../public/img.jpg';
import '../public/script.js';
import '../assets/file.ico';

module.exports = { client: true };
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions e2e_tests/fixtures/build-default/src/public/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
x = 1;
2 changes: 2 additions & 0 deletions e2e_tests/fixtures/build-default/src/server/index.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@

import '../public/img-server.png';

module.exports = { server: true };
16 changes: 16 additions & 0 deletions e2e_tests/tests/kyt-build.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const shell = require('shelljs');
const util = require('../fixtures/util');
const fs = require('fs');

shell.config.silent = true;

Expand All @@ -23,6 +24,21 @@ describe('kyt build', () => {
expect(shell.ls('build/public/main-*.js').code).toBe(0);
expect(shell.ls('build/public/vendor-*.js').code).toBe(0);

// Should fingerprint client and server assets
expect(shell.ls('build/public/img-server-*.png').code).toBe(0);
expect(shell.ls('build/public/img-*.jpg').code).toBe(0);
expect(shell.ls('build/public/script-*.js').code).toBe(0);
expect(shell.ls('build/public/file-*.ico').code).toBe(0);

// Should produce asset manifest mappings for client and server assets and bundles
const manifest = JSON.parse(fs.readFileSync('build/publicAssets.json', 'utf8'));
expect(manifest['img-server.png']).toMatch(/img-server-.*\.png/);
expect(manifest['img.jpg']).toMatch(/img-.*\.jpg/);
expect(manifest['script.js']).toMatch(/script-.*\.js/);
expect(manifest['file.ico']).toMatch(/file-.*\.ico/);
expect(manifest['main.js']).toMatch(/main-.*\.js/);
expect(manifest['vendor.js']).toMatch(/vendor-.*\.js/);

expect(output.code).toBe(0);
});

Expand Down
6 changes: 5 additions & 1 deletion packages/kyt-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,9 @@
"shelljs": "0.7.8",
"simple-git": "1.62.0"
},
"keywords": ["kyt", "cli", "kyt-cli"]
"keywords": [
"kyt",
"cli",
"kyt-cli"
]
}
73 changes: 63 additions & 10 deletions packages/kyt-core/config/webpack.base.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,22 @@
// https://github.com/survivejs/webpack-merge

const path = require('path');
const fs = require('fs');
const webpack = require('webpack');
const shell = require('shelljs');
const { buildPath, userNodeModulesPath, userBabelrcPath } = require('kyt-utils/paths')();
const WebpackAssetsManifest = require('webpack-assets-manifest');
const {
buildPath,
userNodeModulesPath,
userBabelrcPath,
publicSrcPath,
} = require('kyt-utils/paths')();
const fileExtensions = require('./fileExtensions');

module.exports = options => {
const hasBabelrc = shell.test('-f', userBabelrcPath);
const assetsFilePath = path.join(buildPath, options.clientAssetsFile);
let publicAssets = {};

return {
node: {
Expand Down Expand Up @@ -43,25 +52,69 @@ module.exports = options => {
),
},
}),

new WebpackAssetsManifest({
output: assetsFilePath,
space: 2,
writeToDisk: true,
fileExtRegex: /\.\w{2,4}\.(?:map|gz)$|\.\w+$/i,
merge: true,
customize: (key, value) => {
const prependPublicPath = asset => `${options.publicPath || ''}${asset}`;
const removePublicDir = asset => asset.replace(/(.*)?public\//, '');

// For static assets that are only required by the server, we need to
// do some sophisticated work to make sure that their paths are correct.
if (options.type === 'server') {
// If the public assets manifest exists and we haven't already, load it.
if (fs.existsSync(assetsFilePath) && !Object.keys(publicAssets).length) {
// eslint-disable-next-line global-require,import/no-dynamic-require
publicAssets = require(assetsFilePath);
}

// Unfortunately, file-loader appends the `outputPath` (public directory path)
// so we need to remove it from the key and value.
key = removePublicDir(key);
if (publicAssets[key]) {
// If the key already exists in the manifest then we use it. This gets
// around a problem with including chunks from the server build.
value = publicAssets[key];
} else {
value = prependPublicPath(removePublicDir(value));
}
} else {
value = prependPublicPath(value);
}

return { key, value };
},
}),
],

module: {
rules: [
{
test: /\.html$/,
loader: 'file-loader?name=[name].[ext]',
},
{
test: new RegExp(fileExtensions),
loader: 'url-loader',
options: {
limit: 20000,
test: asset => {
const extensions = new RegExp(fileExtensions);
const jsCSSExtensions = new RegExp('\\.(js|css)$');
const isFile = extensions.test(asset);
const isJSOrCSSInPublic = asset.includes('/src/public/') && jsCSSExtensions.test(asset);
return isFile || isJSOrCSSInPublic;
},
loader: 'file-loader',
options:
options.environment === 'development'
? {}
: {
name: '[name]-[hash].[ext]',
publicPath: options.publicPath,
outputPath: asset => (options.type === 'server' ? `../public/${asset}` : asset),
},
},
{
test: /\.(js|jsx)$/,
loader: 'babel-loader',
exclude: [/node_modules/, buildPath],
exclude: [/node_modules/, buildPath, publicSrcPath],
// babel configuration should come from presets defined in the user's
// .babelrc, unless there's a specific reason why it has to be put in
// the webpack loader options
Expand Down
21 changes: 8 additions & 13 deletions packages/kyt-core/config/webpack.dev.client.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
// Development webpack config for client code

const webpack = require('webpack');
const WebpackAssetsManifest = require('webpack-assets-manifest');
const clone = require('lodash.clonedeep');
const path = require('path');
const { clientSrcPath, buildPath, assetsBuildPath } = require('kyt-utils/paths')();
const { clientSrcPath, assetsBuildPath, publicSrcPath } = require('kyt-utils/paths')();
const postcssLoader = require('../utils/getPostcssLoader');

const cssStyleLoaders = [
'style-loader',
{
loader: 'css-loader',
options: { modules: true, sourceMap: true, localIdentName: '[name]-[local]--[hash:base64:5]' },
options: {
modules: true,
sourceMap: true,
localIdentName: '[name]-[local]--[hash:base64:5]',
},
},
postcssLoader,
];
Expand Down Expand Up @@ -57,10 +59,12 @@ module.exports = options => {
{
test: /\.css$/,
use: cssStyleLoaders,
exclude: [publicSrcPath],
},
{
test: /\.scss$/,
use: clone(cssStyleLoaders).concat('sass-loader'),
exclude: [publicSrcPath],
},
],
},
Expand All @@ -70,15 +74,6 @@ module.exports = options => {

new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 1 }),

new WebpackAssetsManifest({
output: path.join(buildPath, options.clientAssetsFile),
space: 2,
writeToDisk: true,
fileExtRegex: /\.\w{2,4}\.(?:map|gz)$|\.\w+$/i,
merge: false,
publicPath: options.publicPath,
}),

new webpack.HotModuleReplacementPlugin(),
],
};
Expand Down
9 changes: 7 additions & 2 deletions packages/kyt-core/config/webpack.dev.server.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,16 @@
const webpack = require('webpack');
const nodeExternals = require('webpack-node-externals');
const clone = require('lodash.clonedeep');
const { serverSrcPath, serverBuildPath } = require('kyt-utils/paths')();
const { serverSrcPath, serverBuildPath, publicSrcPath } = require('kyt-utils/paths')();
const postcssLoader = require('../utils/getPostcssLoader');

const cssStyleLoaders = [
{
loader: 'css-loader/locals',
options: { modules: true, localIdentName: '[name]-[local]--[hash:base64:5]' },
options: {
modules: true,
localIdentName: '[name]-[local]--[hash:base64:5]',
},
},
postcssLoader,
];
Expand Down Expand Up @@ -41,10 +44,12 @@ module.exports = options => ({
{
test: /\.css$/,
use: cssStyleLoaders,
exclude: [publicSrcPath],
},
{
test: /\.scss$/,
use: clone(cssStyleLoaders).concat('sass-loader'),
exclude: [publicSrcPath],
},
],
},
Expand Down
15 changes: 3 additions & 12 deletions packages/kyt-core/config/webpack.prod.client.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@

const webpack = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const WebpackAssetsManifest = require('webpack-assets-manifest');
const clone = require('lodash.clonedeep');
const postcssLoader = require('../utils/getPostcssLoader');
const { clientSrcPath, assetsBuildPath, buildPath } = require('kyt-utils/paths')();
const path = require('path');
const { clientSrcPath, assetsBuildPath, publicSrcPath } = require('kyt-utils/paths')();

const cssStyleLoaders = [
{
Expand Down Expand Up @@ -44,13 +42,15 @@ module.exports = options => ({
fallback: 'style-loader',
use: cssStyleLoaders,
}),
exclude: [publicSrcPath],
},
{
test: /\.scss$/,
loader: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: clone(cssStyleLoaders).concat('sass-loader'),
}),
exclude: [publicSrcPath],
},
],
},
Expand All @@ -77,15 +77,6 @@ module.exports = options => ({
sourceMap: true,
}),

new WebpackAssetsManifest({
output: path.join(buildPath, options.clientAssetsFile),
space: 2,
writeToDisk: true,
fileExtRegex: /\.\w{2,4}\.(?:map|gz)$|\.\w+$/i,
merge: false,
publicPath: options.publicPath,
}),

// Modules should get deterministic ids so that they don't change between builds
new webpack.HashedModuleIdsPlugin(),

Expand Down
4 changes: 3 additions & 1 deletion packages/kyt-core/config/webpack.prod.server.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
const webpack = require('webpack');
const nodeExternals = require('webpack-node-externals');
const clone = require('lodash.clonedeep');
const { serverSrcPath, serverBuildPath } = require('kyt-utils/paths')();
const { serverSrcPath, serverBuildPath, publicSrcPath } = require('kyt-utils/paths')();
const postcssLoader = require('../utils/getPostcssLoader');

const cssStyleLoaders = [
Expand Down Expand Up @@ -44,10 +44,12 @@ module.exports = options => ({
{
test: /\.css$/,
use: cssStyleLoaders,
exclude: [publicSrcPath],
},
{
test: /\.scss$/,
use: clone(cssStyleLoaders).concat('sass-loader'),
exclude: [publicSrcPath],
},
],
},
Expand Down
10 changes: 7 additions & 3 deletions packages/kyt-core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "kyt",
"version": "0.8.0",
"version": "0.9.0-alpha.1",
"description": "kyt is a toolkit that encapsulates and manages the configuration for web apps.",
"author": "NYTimes",
"license": "Apache-2.0",
Expand Down Expand Up @@ -69,12 +69,16 @@
"temp": "0.8.3",
"url-loader": "0.5.8",
"webpack": "3.1.0",
"webpack-assets-manifest": "0.6.2",
"webpack-assets-manifest": "0.7.0",
"webpack-dev-middleware": "1.11.0",
"webpack-dev-server": "2.5.1",
"webpack-hot-middleware": "2.18.2",
"webpack-merge": "4.1.0",
"webpack-node-externals": "1.6.0"
},
"keywords": ["kyt", "core", "kyt-core"]
"keywords": [
"kyt",
"core",
"kyt-core"
]
}

0 comments on commit 9150e93

Please sign in to comment.