UNPKG

3 kBJavaScriptView Raw
1const path = require('path');
2
3const PATH_DELIMITER = '[\\\\/]'; // match 2 antislashes or one slash
4
5/**
6 * Stolen from https://stackoverflow.com/questions/10776600/testing-for-equality-of-regular-expressions
7 */
8const regexEqual = (x, y) => {
9 return (x instanceof RegExp) && (y instanceof RegExp) &&
10 (x.source === y.source) && (x.global === y.global) &&
11 (x.ignoreCase === y.ignoreCase) && (x.multiline === y.multiline);
12};
13
14const generateIncludes = (modules) => {
15 return modules.map(module => (new RegExp(`${safePath(module)}(?!.*node_modules)`)));
16};
17
18const generateExcludes = (modules) => {
19 return [new RegExp(`node_modules${PATH_DELIMITER}(?!(${modules.map(safePath).join('|')})(?!.*node_modules))`)];
20};
21
22/**
23 * On Windows, the Regex won't match as Webpack tries to resolve the
24 * paths of the modules. So we need to check for \\ and /
25 */
26const safePath = (module) => module.split('/').join(PATH_DELIMITER);
27
28/**
29 * Actual Next.js plugin
30 */
31const withTm = (nextConfig = {}) => {
32 const { transpileModules = [] } = nextConfig;
33 const includes = generateIncludes(transpileModules);
34 const excludes = generateExcludes(transpileModules);
35
36 return Object.assign({}, nextConfig, {
37 webpack (config, options) {
38 // Safecheck for Next < 5.0
39 if (!options.defaultLoaders) {
40 throw new Error(
41 'This plugin is not compatible with Next.js versions below 5.0.0 https://err.sh/next-plugins/upgrade'
42 );
43 }
44
45 // Avoid Webpack to resolve transpiled modules path to their real path
46 config.resolve.symlinks = false;
47
48 config.externals = config.externals.map(external => {
49 if (typeof external !== 'function') return external;
50 return (ctx, req, cb) => {
51 return includes.find(include =>
52 req.startsWith('.')
53 ? include.test(path.resolve(ctx, req))
54 : include.test(req)
55 )
56 ? cb()
57 : external(ctx, req, cb);
58 };
59 });
60
61 // Add a rule to include and parse all modules
62 config.module.rules.push({
63 test: /\.+(js|jsx|ts|tsx)$/,
64 loader: options.defaultLoaders.babel,
65 include: includes
66 });
67
68 if (typeof nextConfig.webpack === 'function') {
69 return nextConfig.webpack(config, options);
70 }
71
72 return config;
73 },
74
75 // webpackDevMiddleware needs to be told to watch the changes in the
76 // transpiled modules directories
77 webpackDevMiddleware (config) {
78 // Replace /node_modules/ by the new exclude RegExp (including the modules
79 // that are going to be transpiled)
80 const ignored = config.watchOptions.ignored.filter(
81 regexp => !regexEqual(regexp, /[\\/]node_modules[\\/]/)
82 ).concat(excludes);
83
84 config.watchOptions.ignored = ignored;
85
86 if (typeof nextConfig.webpackDevMiddleware === 'function') {
87 return nextConfig.webpackDevMiddleware(config);
88 }
89
90 return config;
91 }
92 });
93};
94
95module.exports = withTm;