Skip to content

Commit

Permalink
feat: add helpers for file-loader
Browse files Browse the repository at this point in the history
We internally set a few useful things for file-loader to work
properly with js/ts and css files. But when it is needed outside
it becomes very difficult. To solve this, we create helper utils
and expose them through node.js APIs.

This solves the problem as raised in #284
  • Loading branch information
swashata committed Apr 15, 2019
1 parent 0ab7e5b commit 49bd29c
Show file tree
Hide file tree
Showing 12 changed files with 260 additions and 54 deletions.
2 changes: 2 additions & 0 deletions examples/plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
"cssnano": "^4.1.10",
"fork-ts-checker-webpack-plugin": "^1.0.2",
"node-sass": "^4.11.0",
"svgo": "^1.2.1",
"svgo-loader": "^2.2.0",
"typescript": "^3.4.3"
},
"scripts": {
Expand Down
4 changes: 4 additions & 0 deletions examples/plugin/src/app/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,7 @@ body {
background: url('./image.png') no-repeat top left;
background-size: 100px 70px;
}
.hentry {
background: url('./svg.svg') no-repeat top left;
background-size: 100px 70px;
}
2 changes: 2 additions & 0 deletions examples/plugin/src/app/index.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import './index.css';
import imgURL from './image.png';
import logger from './modules/logger';
import svgURL from './svg.svg';

console.log('Heres an URL of dynamically imported asset.');
console.log(imgURL);
console.log(svgURL);

console.log('I can not be hot-reloaded!');
console.log('But my imports can be😉!@');
Expand Down
8 changes: 8 additions & 0 deletions examples/plugin/src/app/svg.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
51 changes: 50 additions & 1 deletion examples/plugin/wpackio.project.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// include a few node-js APIs
const { getFileLoaderOptions, issuerForNonStyleFiles, issuerForStyleFiles } = require('@wpackio/scripts');

module.exports = {
// Project Identity
appName: 'wpackplugin', // Unique name of your project
Expand All @@ -24,7 +27,53 @@ module.exports = {
mobile: ['./src/app/mobile.js'],
},
// Extra webpack config to be passed directly
webpackConfig: undefined,
webpackConfig: (config, api, appDir, isDev) => {
const svgoLoader = {
loader: 'svgo-loader',
options: {
plugins: [
{ removeTitle: true },
{ convertColors: { shorthex: false } },
{ convertPathData: false },
],
},
};
// create module rules
const configWithSvg = {
module: {
rules: [
// SVGO Loader
// https://github.com/rpominov/svgo-loader
// This rule handles SVG for javascript files
{
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'file-loader',
options: getFileLoaderOptions(appDir, isDev, false),
},
svgoLoader,
],
issuer: issuerForNonStyleFiles,
},
// This rule handles SVG for style files
{
test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
use: [
{
loader: 'file-loader',
options: getFileLoaderOptions(appDir, isDev, true),
},
svgoLoader,
],
issuer: issuerForStyleFiles,
},
]
}
};
// merge the new module.rules with webpack-merge api
return api(config, configWithSvg);
},
},
// If has more length, then multi-compiler
{
Expand Down
26 changes: 11 additions & 15 deletions examples/plugin/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -853,11 +853,6 @@
"@types/node" "*"
"@types/range-parser" "*"

"@types/figlet@^1.2.0":
version "1.2.0"
resolved "https://registry.yarnpkg.com/@types/figlet/-/figlet-1.2.0.tgz#2dab76da069dc8ce5dcab461f7f2788317fb01a8"
integrity sha512-TDZkNpYfkc3X8yv7w1QBziZmmxzNfGKX+YjeNkMpmSiNV0QOdNf9G5cEZB3FH1/oaqpSQEdxuDzURdju2L3lng==

"@types/figures@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@types/figures/-/figures-2.0.0.tgz#e624a9ad71db49b9c8b9bbd59fe1ad04c443913c"
Expand Down Expand Up @@ -1198,7 +1193,6 @@
"@types/archiver" "^2.1.3"
"@types/browser-sync" "^0.0.43"
"@types/execa" "^0.9.0"
"@types/figlet" "^1.2.0"
"@types/figures" "^2.0.0"
"@types/find-up" "^2.1.1"
"@types/gradient-string" "^1.1.0"
Expand Down Expand Up @@ -1226,7 +1220,6 @@
del "^4.1.0"
dev-ip "^1.0.1"
execa "^1.0.0"
figlet "^1.2.1"
figures "^2.0.0"
file-loader "^3.0.1"
find-up "^3.0.0"
Expand Down Expand Up @@ -3531,11 +3524,6 @@ figgy-pudding@^3.5.1:
resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790"
integrity sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w==

figlet@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/figlet/-/figlet-1.2.1.tgz#48d35df9d9b10b1b3888302e6e57904a0b00509c"
integrity sha512-qc8gycfnnfOmfvPl7Fi3JeTbcvdmbZkckyUVGGAM02je7Ookvu+bBfKy1I4FKqTsQHCs3ARJ76ip/k98r+OQuQ==

figures@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962"
Expand Down Expand Up @@ -4786,7 +4774,7 @@ js-tokens@^3.0.2:
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b"
integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls=

js-yaml@^3.13.0, js-yaml@^3.9.0:
js-yaml@^3.12.0, js-yaml@^3.13.0, js-yaml@^3.9.0:
version "3.13.1"
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847"
integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==
Expand Down Expand Up @@ -4963,7 +4951,7 @@ [email protected]:
emojis-list "^2.0.0"
json5 "^0.5.0"

loader-utils@^1.0.1, loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3:
loader-utils@^1.0.1, loader-utils@^1.0.2, loader-utils@^1.0.3, loader-utils@^1.1.0, loader-utils@^1.2.3:
version "1.2.3"
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7"
integrity sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==
Expand Down Expand Up @@ -7870,7 +7858,15 @@ supports-color@^6.1.0:
dependencies:
has-flag "^3.0.0"

svgo@^1.0.0:
svgo-loader@^2.2.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/svgo-loader/-/svgo-loader-2.2.0.tgz#f29eb43efc14c34a15c4023f56ba12775ccdbe5f"
integrity sha512-AtIy4kmUQc1zo+QK3ZFvRrULRZAhUC63cLJxdVo1cONZ9WeYAkySUlaB05uZKKcYpsTb/9tDsBSXMab3/0QWtw==
dependencies:
js-yaml "^3.12.0"
loader-utils "^1.0.3"

svgo@^1.0.0, svgo@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.2.1.tgz#3fedde75a4016193e1c2608b5fdef6f3e4a9fd99"
integrity sha512-Y1+LyT4/y1ms4/0yxPMSlvx6dIbgklE9w8CIOnfeoFGB74MEkq8inSfEr6NhocTaFbyYp0a1dvNgRKGRmEBlzA==
Expand Down
7 changes: 6 additions & 1 deletion packages/scripts/src/config/CreateWebpackConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,12 @@ export class CreateWebpackConfig {
if (file.webpackConfig != null) {
// If it is a function
if (typeof file.webpackConfig === 'function') {
config = file.webpackConfig(config, webpackMerge);
config = file.webpackConfig(
config,
webpackMerge,
helper.getAppDir(),
this.isDev
);
} else {
config = webpackMerge(config, file.webpackConfig);
}
Expand Down
48 changes: 12 additions & 36 deletions packages/scripts/src/config/WebpackConfigHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
webpackOptionsOverrideFunction,
} from './project.config.default';
import { ServerConfig } from './server.config.default';
import { getFileLoaderForJsAndStyleAssets } from './fileLoader';

interface NormalizedEntry {
[x: string]: string[];
Expand Down Expand Up @@ -487,42 +488,10 @@ ${bannerConfig.copyrightText}${bannerConfig.credit ? creditNote : ''}`,
});
}
// create file rules
// But use relativePath for style type resources like sass, scss or css
// This is needed because we can't know the absolute publicPath
// of CSS imported assets.
const fileLoaderTest = /\.(woff|woff2|eot|ttf|otf|png|jpg|gif)(\?v=\d+\.\d+\.\d+)?$/;
const fileLoaderOptions = {
name: `[name]-[hash:8].[ext]`,
outputPath: `${this.appDir}/assets/`,
};
const fileRulesNonStyle: webpack.RuleSetRule = {
test: fileLoaderTest,
use: [
{
loader: 'file-loader',
options: {
...fileLoaderOptions,
},
},
],
issuer: location => !/\.(sa|sc|c)ss$/.test(location),
};
const fileRulesStyle: webpack.RuleSetRule = {
test: fileLoaderTest,
use: [
{
loader: 'file-loader',
options: {
...fileLoaderOptions,
// Here mention the public path relative to the css
// file directory, but only during production mode
// for development mode, it is still undefined
publicPath: this.isDev ? undefined : `assets/`,
},
},
],
issuer: location => /\.(sa|sc|c)ss$/.test(location),
};
const {
fileRulesNonStyle,
fileRulesStyle,
} = getFileLoaderForJsAndStyleAssets(this.appDir, this.isDev);

return {
rules: [
Expand Down Expand Up @@ -634,4 +603,11 @@ ${bannerConfig.copyrightText}${bannerConfig.credit ? creditNote : ''}`,
return false;
}
}

/**
* Get calculated app directory
*/
public getAppDir(): string {
return this.appDir;
}
}
94 changes: 94 additions & 0 deletions packages/scripts/src/config/fileLoader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import webpack from 'webpack';

/**
* This file holds useful utility functions for file-loader
*/

/**
* Get options for file-loader.
*
* This takes into account the appDir, development or production mode and
* publicPath for file-loader usage from css files.
*
* @param appDir Application directory (corresponds to files[i].name).
* @param isDev Whether this is for development or production build.
* @param publicPath Whether to include publicPath.
*/
export function getFileLoaderOptions(
appDir: string,
isDev: boolean,
publicPath: boolean
) {
const fileLoaderOptions: { [x: string]: string | undefined } = {
name: `[name]-[hash:8].[ext]`,
outputPath: `${appDir}/assets/`,
};
if (publicPath) {
// Here mention the public path relative to the css
// file directory, but only during production mode
// for development mode, it is still undefined
fileLoaderOptions.publicPath = isDev ? undefined : `assets/`;
}
return fileLoaderOptions;
}

/**
* Webpack module.rules[].issuer function to check if the issuer is
* a style file (scss, sass, css).
*/
export function issuerForStyleFiles(location: string): boolean {
return /\.(sa|sc|c)ss$/.test(location);
}

/**
* Webpack module.rules[].issuer function to check if the issuer is NOT
* a style file (scss, sass, css).
*/
export function issuerForNonStyleFiles(location: string): boolean {
return !/\.(sa|sc|c)ss$/.test(location);
}

/**
* Get file-loader with proper options set for javascript and style files.
*
* It makes sure that assets are put into proper directory and relativePath
* works fine for css imports.
*
* @param appDir Application directory (corresponds to files[i].name).
* @param isDev Whether this is for development or production build.
* @param loader Name of the loader, defaults to `file-loader`.
*/
export function getFileLoaderForJsAndStyleAssets(
appDir: string,
isDev: boolean,
loader: string = 'file-loader'
) {
// create file rules
// But use relativePath for style type resources like sass, scss or css
// This is needed because we can't know the absolute publicPath
// of CSS imported assets.
const fileLoaderTest = /\.(woff|woff2|eot|ttf|otf|png|jpg|gif)(\?v=\d+\.\d+\.\d+)?$/;

const fileRulesNonStyle: webpack.RuleSetRule = {
test: fileLoaderTest,
use: [
{
loader,
options: getFileLoaderOptions(appDir, isDev, false),
},
],
issuer: issuerForNonStyleFiles,
};
const fileRulesStyle: webpack.RuleSetRule = {
test: fileLoaderTest,
use: [
{
loader,
options: getFileLoaderOptions(appDir, isDev, true),
},
],
issuer: issuerForStyleFiles,
};

return { fileRulesNonStyle, fileRulesStyle };
}
4 changes: 3 additions & 1 deletion packages/scripts/src/config/project.config.default.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ export interface FileConfig {
| webpack.Configuration
| ((
config: webpack.Configuration,
api: merge
api: merge,
appDir: string,
isDev: boolean
) => webpack.Configuration);
}

Expand Down
7 changes: 7 additions & 0 deletions packages/scripts/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,13 @@ export {
serverConfigDefault,
} from './config/server.config.default';

export {
getFileLoaderForJsAndStyleAssets,
getFileLoaderOptions,
issuerForNonStyleFiles,
issuerForStyleFiles,
} from './config/fileLoader';

// Expose all needed script classes
export { Build } from './scripts/Build';

Expand Down
Loading

0 comments on commit 49bd29c

Please sign in to comment.