Switching from NPM to PNPM - Absolute File Paths Break in React Project - reactjs

So npm was getting really slow for CircleCi and my builds were timing out and running into memory issues. So I wanted to switch to pnpm. Upon switching to pnpm I noticed that any .js file in my react project that are using an absolute path no longer work and wants me to turn them all into relative paths. Not sure if this is a bug with the version or I'm doing something wrong but it all i did was delete my package-lock.json and deleted my node_modules and installed pnpm#5 then ran pnpm i and then built my project as I've always done
npm -v 6.13.4
node -v 12.16.0
pnpm -v 5.18.0
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11",
Error has occured: ModuleNotFoundError: Module not found: Error: Can't resolve 'Root' in '/Users/Olive/dashboard/src'
Parsed request is a module
using description file: /Users/Olive/dashboard/package.json (relative path: ./src)
resolve as module
/Users/Olive/dashboard/src/node_modules doesn't exist or is not a directory
/Users/Olive/node_modules doesn't exist or is not a directory
/Users/node_modules doesn't exist or is not a directory
/Users/node_modules doesn't exist or is not a directory
/node_modules doesn't exist or is not a directory
looking for modules in /Users/Olive/dashboard/node_modules
using description file: /Users/Olive/dashboard/package.json (relative path: ./node_modules)
using description file: /Users/Olive/dashboard/package.json (relative path: ./node_modules/Root)
no extension
/Users/Olive/dashboard/node_modules/Root doesn't exist
.web.js
/Users/Olive/dashboard/node_modules/Root.web.js doesn't exist
.mjs
/Users/Olive/dashboard/node_modules/Root.mjs doesn't exist
.js
/Users/Olive/dashboard/node_modules/Root.js doesn't exist
.json
/Users/Olive/dashboard/node_modules/Root.json doesn't exist
.web.jsx
/Users/Olive/dashboard/node_modules/Root.web.jsx doesn't exist
.jsx
/Users/Olive/dashboard/node_modules/Root.jsx doesn't exist
as directory
/Users/Olive/dashboard/node_modules/Root doesn't exist
looking for modules in /Users/Olive/dashboard/node_modules
using description file: /Users/Olive/dashboard/package.json (relative path: ./node_modules)
using description file: /Users/Olive/dashboard/package.json (relative path: ./node_modules/Root)
no extension
/Users/Olive/dashboard/node_modules/Root doesn't exist
.web.js
/Users/Olive/dashboard/node_modules/Root.web.js doesn't exist
.mjs
/Users/Olive/dashboard/node_modules/Root.mjs doesn't exist
.js
/Users/Olive/dashboard/node_modules/Root.js doesn't exist
.json
/Users/Olive/dashboard/node_modules/Root.json doesn't exist
.web.jsx
/Users/Olive/dashboard/node_modules/Root.web.jsx doesn't exist
.jsx
/Users/Olive/dashboard/node_modules/Root.jsx doesn't exist
as directory
/Users/Olive/dashboard/node_modules/Root doesn't exist
Before
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from "react-router-dom";
import registerServiceWorker from 'registerServiceWorker';
import Root from 'Root';
ReactDOM.render(
<BrowserRouter>
<Root/>
</BrowserRouter>,
document.getElementById('root'));
registerServiceWorker();
After: What it wants me to do to my absolute paths -> relative paths
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from "react-router-dom";
import registerServiceWorker from './registerServiceWorker'; // Changed this
import Root from './Root'; // Changed this
ReactDOM.render(
<BrowserRouter>
<Root/>
</BrowserRouter>,
document.getElementById('root'));
registerServiceWorker();
webpack file
'use strict';
const autoprefixer = require('autoprefixer');
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
const WatchMissingNodeModulesPlugin = require('react-dev-utils/WatchMissingNodeModulesPlugin');
const eslintFormatter = require('react-dev-utils/eslintFormatter');
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
const getClientEnvironment = require('./env');
const paths = require('./paths');
const publicPath = '/';
const publicUrl = '';
const env = getClientEnvironment(publicUrl);
module.exports = {
devtool: 'cheap-module-source-map',
entry: [
require.resolve('./polyfills'),
require.resolve('react-dev-utils/webpackHotDevClient'),
paths.appIndexJs,
],
mode: 'development',
output: {
pathinfo: true,
filename: 'static/js/bundle.js',
chunkFilename: 'static/js/[name].chunk.js',
publicPath: publicPath,
devtoolModuleFilenameTemplate: info =>
path.resolve(info.absoluteResourcePath).replace(/\\/g, '/'),
},
resolve: {
modules: ['node_modules', paths.appNodeModules].concat(
// It is guaranteed to exist because we tweak it in `env.js`
process.env.NODE_PATH.split(path.delimiter).filter(Boolean)
),
extensions: ['.web.js', '.mjs', '.js', '.json', '.web.jsx', '.jsx'],
alias: {
'react-native': 'react-native-web',
},
plugins: [
new ModuleScopePlugin(paths.appSrc, [paths.appPackageJson]),
],
},
module: {
strictExportPresence: true,
rules: [
{
test: /\.(js|jsx|mjs)$/,
enforce: 'pre',
use: [
{
options: {
formatter: eslintFormatter,
eslintPath: require.resolve('eslint'),
},
loader: require.resolve('eslint-loader'),
},
],
include: paths.appSrc,
},
{
oneOf: [
{
test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/],
loader: require.resolve('url-loader'),
options: {
limit: 10000,
name: 'static/media/[name].[hash:8].[ext]',
},
},
// Process JS with Babel.
{
test: /\.(js|jsx|mjs)$/,
include: paths.appSrc,
loader: require.resolve('babel-loader'),
options: {
cacheDirectory: true,
plugins: [
["syntax-async-functions"],
["#babel/plugin-proposal-decorators", { "legacy": true}],
]
},
},
{
test: /\.css$/,
use: [
require.resolve('style-loader'),
{
loader: require.resolve('css-loader'),
options: {
importLoaders: 1,
},
},
{
loader: require.resolve('postcss-loader'),
options: {
// Necessary for external CSS imports to work
// https://github.com/facebookincubator/create-react-app/issues/2677
ident: 'postcss',
plugins: () => [
require('postcss-flexbugs-fixes'),
autoprefixer({
flexbox: 'no-2009',
}),
],
},
},
],
},
{
exclude: [/\.(js|jsx|mjs)$/, /\.html$/, /\.json$/],
loader: require.resolve('file-loader'),
options: {
name: 'static/media/[name].[hash:8].[ext]',
},
},
],
},
],
},
plugins: [
new HtmlWebpackPlugin({
inject: true,
template: paths.appHtml,
}),
new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw),
new webpack.DefinePlugin(env.stringified),
new webpack.HotModuleReplacementPlugin(),
new CaseSensitivePathsPlugin(),
new WatchMissingNodeModulesPlugin(paths.appNodeModules),
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
],
node: {
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty',
},
performance: {
hints: false,
},
};
module.exports.parallelism = 1;
jsconfig.json
{
"compilerOptions": {
"experimentalDecorators": true,
"baseUrl": "src"
},
"include": [
"src"
]
}
I'm also getting this warning which I wasn't getting when using npm
ExperimentalWarning: Package name self resolution is an experimental feature. This feature could change at any time
With yarn I also get the same error as above, but then this special failure
./node_modules/enzyme/node_modules/htmlparser2/lib/esm/index.js 59:9
Module parse failed: Unexpected token (59:9)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| return getFeed(parseDOM(feed, options));
| }
> export * as DomUtils from "domutils";
| // Old name for DomHandler
| export { DomHandler as DefaultHandler };
https://github.com/cheeriojs/cheerio/issues/2545
This did not work

Related

SVGs and PNGs not loading

I am working on a micro frontend using Webpack.
And I have a problem where all local my SVGs and PNGs are not being loaded by Webpack5 react app. I keep getting 404 when doing that.
Can anyone point me out what I am doing wrong?
Here is the folder structuring
/public
/src
/components
navbar.tsx
/assets
Logo.svg
webpack.config.js
Here is my Webpack config. I am including the loader for assets, as indicated in the Webpack documentation
Webpack.config.js
const HtmlWebPackPlugin = require("html-webpack-plugin");
const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");
const deps = require("./package.json").dependencies;
module.exports = {
output: {
publicPath: "http://localhost:3000/",
},
resolve: {
extensions: [".vue", ".tsx", ".ts", ".jsx", ".js", ".json"],
},
devServer: {
port: 3000,
historyApiFallback: true,
},
module: {
rules: [
{
test: /\.m?js/,
type: "javascript/auto",
resolve: {
fullySpecified: false,
},
},
{
test: /\.(css|s[ac]ss)$/i,
use: ["style-loader", "css-loader", "postcss-loader"],
},
{
test: /\.(ts|tsx|js|jsx)$/,
exclude: /node_modules/,
use: { loader: "babel-loader" },
},
{
test: /\.(png|svg|jpg|jpeg|gif)$/i,
type: 'asset/resource',
},
],
},
plugins: [
new ModuleFederationPlugin({
name: "App1",
filename: "remoteEntry.js",
remotes: {},
exposes: {},
shared: {
...deps,
react: {
singleton: true,
requiredVersion: deps.react,
},
"react-dom": {
singleton: true,
requiredVersion: deps["react-dom"],
},
},
}),
new HtmlWebPackPlugin({
template: "./src/index.html",
}),
],
};
And here is one of the images imported in the Navbar.
Navbar.tsx
import React from "react";
export default function Navbar() {
return (
<img src="./assets/Logo.svg" alt="Logo" />
)
}
I'm not an expert in react but with the app rendered in App.js maybe your url img src should be something like src='./components/assets/ because it would start from the src folder ? (i know if it's an import it works as expected but here it's a src ..)
Feel free to delete i didn't have enough karma to comment

React with Webpack, Typescript and Cypress Loader Error

I'm trying to configure cypress with a working configuration of webpack with React and Typescript. It seems to me that the babel-loader is not picking up the cypress/support/components.ts file because my webpack entry is ./src/index.tsx and the cypress folder is on the root not inside src.
Here is the error I'm getting...
========
Error: The following error originated from your test code, not from Cypress.
Module parse failed: Unexpected token (28:8)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| // Alternatively, can be defined in cypress/support/component.d.ts
| // with a at the top of your spec.
declare global {
| namespace Cypress {
| interface Chainable {
When Cypress detects uncaught errors originating from your test code it will automatically fail the current test.
Cypress could not associate this error to any specific test.
We dynamically generated a new test to display this failure.
===========
Here is my cypress.config.ts
import { defineConfig } from 'cypress';
export default defineConfig({
component: {
devServer: {
framework: 'react',
bundler: 'webpack',
webpackConfig: require('./webpack.dev'),
},
includeShadowDom: true,
},
});
Here is my webpack.common.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
module.exports = {
entry: {
main: './src/index.tsx',
},
plugins: [
new HtmlWebpackPlugin({
template: path.join(__dirname, 'src', 'index.html'),
}),
],
module: {
rules: [
{
test: /\.(js|ts)x$/,
exclude: /node_modules/,
use: ['babel-loader'],
},
{
test: /\.(png|jpg)$/,
use: {
loader: 'file-loader',
options: {
name: '[name].[contenthash].[ext]',
outputPath: 'static/images',
},
},
},
{
test: /\.svg$/,
use: [
{
loader: '#svgr/webpack',
options: {
name: '[name].[contenthash].[ext]',
outputPath: 'static/images',
},
},
{
loader: 'file-loader',
options: {
name: '[name].[contenthash].[ext]',
outputPath: 'static/images',
},
},
],
},
{
test: /\.(woff|woff2)$/,
type: 'asset/resource',
generator: {
filename: 'static/fonts/[name][ext][query]',
},
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.jsx', '.js'],
plugins: [new TsconfigPathsPlugin()],
},
};
Here is my webpack.dev.js
const path = require('path');
const { merge } = require('webpack-merge');
const common = require('./webpack.common');
module.exports = merge(common, {
mode: 'development',
devServer: {
port: '9500',
static: {
directory: path.join(__dirname, 'src'),
},
open: false,
},
module: {
rules: [
{
test: /\.css$/,
use: [
'style-loader', // 2) injects styles into DOM
'css-loader', // 1) turns css into commonjs
],
},
],
},
devtool: 'eval-source-map',
});
Again this config is working and will build, the issue I'm have is bringing in Cypress using Typescript for our testing suite.
I've tried all sorts of different configs and using ts-loader with babel-loader, but I feel like I'm just missing how to get webpack to "pick up" the .ts files in the Cypress folder with is outside of my src.
Any suggestions are very much appreciated!

webpack.config with font-awesome

I am going to use fontawesome 5 in my source code, but I have some trouble here.
I've installed 4 npm modules.
"#fortawesome/fontawesome-free": "^5.11.2",
"#fortawesome/fontawesome-svg-core": "^1.2.25",
"#fortawesome/free-solid-svg-icons": "^5.11.2",
"#fortawesome/react-fontawesome": "^0.1.7",
webpack.config.js
'use strict';
/**
* Webpack Config
*/
const path = require('path');
const fs = require('fs');
const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin');
// const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
// Webpack uses `publicPath` to determine where the app is being served from.
// In development, we always serve from the root. This makes config easier.
const publicPath = '/';
// Make sure any symlinks in the project folder are resolved:
const appDirectory = fs.realpathSync(process.cwd());
const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
// plugins
const HtmlWebPackPlugin = require("html-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const CleanWebpackPlugin = require('clean-webpack-plugin');
const UglifyJsPlugin = require('uglifyjs-webpack-plugin');
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");
const CopyWebpackPlugin = require('copy-webpack-plugin');
// the path(s) that should be cleaned
let pathsToClean = [
'dist',
'build'
]
// the clean options to use
let cleanOptions = {
root: __dirname,
verbose: false, // Write logs to console.
dry: false
}
module.exports = {
entry: ["babel-polyfill", "react-hot-loader/patch", "./src/index.js"],
output: {
// The build folder.
path: resolveApp('build'),
// Generated JS file names (with nested folders).
// There will be one main bundle, and one file per asynchronous chunk.
// We don't currently advertise code splitting but Webpack supports it.
filename: 'assets/js/[name].[hash:8].js',
chunkFilename: 'assets/js/[name].[hash:8].chunk.js',
// We inferred the "public path" (such as / or /my-project) from homepage.
publicPath: publicPath,
hotUpdateChunkFilename: 'hot/hot-update.js',
hotUpdateMainFilename: 'hot/hot-update.json'
},
devServer: {
contentBase: './src/index.js',
compress: true,
port: 3000, // port number
historyApiFallback: true,
quiet: true
},
// resolve alias (Absolute paths)
resolve: {
alias: {
Components: path.resolve(__dirname, 'src/components/'),
Containers: path.resolve(__dirname, 'src/containers/'),
Assets: path.resolve(__dirname, 'src/assets/'),
Util: path.resolve(__dirname, 'src/util/'),
Routes: path.resolve(__dirname, 'src/routes/'),
Constants: path.resolve(__dirname, 'src/constants/'),
Redux: path.resolve(__dirname, 'src/redux/'),
Data: path.resolve(__dirname, 'src/data/')
}
},
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
{
test: /\.html$/,
use: [
{
loader: "html-loader",
options: { minimize: true }
}
]
},
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, "css-loader"]
},
// Scss compiler
{
test: /\.scss$/,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
"sass-loader"
]
}
]
},
optimization: {
minimizer: [
new UglifyJsPlugin({
cache: true,
parallel: true,
uglifyOptions: {
compress: false,
ecma: 6,
mangle: true
},
sourceMap: true
}),
new OptimizeCSSAssetsPlugin({})
]
},
performance: {
hints: process.env.NODE_ENV === 'production' ? "warning" : false
},
plugins: [
new CopyWebpackPlugin([
{ from: 'src/assets/img', to: 'assets/img' }, { from: 'src/assets/fonts', to: 'assets/fonts' }
]),
new FriendlyErrorsWebpackPlugin(),
new CleanWebpackPlugin(pathsToClean, cleanOptions),
new HtmlWebPackPlugin({
template: "./public/index.html",
filename: "./index.html",
favicon: './public/favicon.ico'
}),
new MiniCssExtractPlugin({
filename: "assets/css/[name].[hash:8].css"
}),
new MiniCssExtractPlugin({
filename: "[name].[hash:8].css",
chunkFilename: "[id].[hash:8].css"
})
]
};
And I've got below error when I wrote import '#fortawesome/fontawesome-free/css/solid.css';
Failed to compile with 1 errors 3:21:04 AM
error in ./node_modules/#fortawesome/fontawesome-free/css/solid.css
Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js):
ModuleParseError: Module parse failed: Unexpected character ' ' (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
(Source code omitted for this binary file)
at handleParseError (E:\workspace\pulse\projectai-pulse-survey\node_modules\webpack\lib\NormalModule.js:469:19)
at doBuild.err (E:\workspace\pulse\projectai-pulse-survey\node_modules\webpack\lib\NormalModule.js:503:5)
at runLoaders (E:\workspace\pulse\projectai-pulse-survey\node_modules\webpack\lib\NormalModule.js:358:12)
at E:\workspace\pulse\projectai-pulse-survey\node_modules\loader-runner\lib\LoaderRunner.js:373:3
at iterateNormalLoaders (E:\workspace\pulse\projectai-pulse-survey\node_modules\loader-runner\lib\LoaderRunner.js:214:10)
at Array.<anonymous> (E:\workspace\pulse\projectai-pulse-survey\node_modules\loader-runner\lib\LoaderRunner.js:205:4)
at Storage.finished (E:\workspace\pulse\projectai-pulse-survey\node_modules\webpack\node_modules\enhanced-resolve\lib\CachedInputFileSystem.js:55:16) at provider (E:\workspace\pulse\projectai-pulse-survey\node_modules\webpack\node_modules\enhanced-resolve\lib\CachedInputFileSystem.js:91:9)
at E:\workspace\pulse\projectai-pulse-survey\node_modules\graceful-fs\graceful-fs.js:115:16
at FSReqWrap.readFileAfterClose [as oncomplete] (internal/fs/read_file_context.js:53:3)
# ./src/components/MyMap/KGraph/index.js 17:0-54
# ./src/components/MyMap/index.js
# ./src/routes/mymap/index.js
# ./src/routes/index.js
# ./src/containers/App.js
# ./src/App.js
# ./src/index.js
# multi babel-polyfill react-hot-loader/patch ./src/index.js
I've tried to many ways to solve this, but all are failed.
Please help me.
In my case in file-loader or url-loader instead of testing for only image file extentions, I've also added font extentions like this:
module: {
rules: [
{
test: /\.(png|svg|jpg|jpeg|gif|woff|woff2|eot|ttf|)$/i,
use: [
{
loader: "file-loader",
options: {//your options},
}
// ...other loaders here
],
},
]
}
Try to change the import of the ‘CSS’ file to import ’'~#fortawesome/fontawesome-free/css/solid.css'’, as suggested here.
Solved!
I've added the below codes to webpack.config.js
module: {
rules: [
...
{
test: /\.(png|woff|woff2|eot|ttf|svg)$/,
loader: 'url-loader?limit=100000'
}
]
}
Thanks

Webpack 4: Module parse failed: Unexpected token

During my builds, webpack is giving me this error:
ERROR in ./client/components/App/index.tsx 15:9
Module parse failed: Unexpected token (15:9)
You may need an appropriate loader to handle this file type.
|
|
> const App: SFC = () => (
| <div style={{ background: "red" }}>
| <h3>test</h3>
# ./client/index.tsx 11:4-14:6 12:24-51
# multi react-hot-loader/patch ./client/index.tsx webpack-hot-middleware/client?path=/__webpack_hmr&timeout=20000&reload=true
Here is my webpack.config.ts:
import CleanWebpackPlugin from "clean-webpack-plugin";
import HtmlWebpackPlugin from "html-webpack-plugin";
import path from "path";
import { Configuration, HotModuleReplacementPlugin } from "webpack";
const rootDir = ["..", "..", "..", ".."];
const distDir = ["..", ".."];
// this file lives in one place as `.ts` and another as `.js` grab the
// file extension to determine the include path relative to its location
const include =
path.extname(module.id) === ".ts"
? path.resolve(__dirname, "client", "index.tsx")
: path.resolve(__dirname, ...rootDir, "client", "index.tsx");
const exclude = /node_modules/;
const tsconfig = path.resolve(
__dirname,
...rootDir,
"config",
"tsconfig.client.json"
);
// development plugins
const plugins = [
new HotModuleReplacementPlugin(),
new HtmlWebpackPlugin({
template: path.resolve(__dirname, "..", "..", "..", "index.html")
}),
new CleanWebpackPlugin([path.resolve(__dirname, ...distDir, "*.*")], {
allowExternal: true,
root: __dirname,
verbose: true
})
];
// script for webpack-hot-middleware
const hotMiddlewareScript: string =
"webpack-hot-middleware/client?path=/__webpack_hmr&timeout=20000&reload=true";
const webpackDevConfig: Configuration = {
context: path.resolve(__dirname, ...rootDir),
devtool: "source-map",
entry: {
app: ["react-hot-loader/patch", include, hotMiddlewareScript]
},
mode: "development",
module: {
rules: [
{
exclude,
include,
test: /\.css$/,
use: ["style-loader", "css-loader"]
},
{
exclude,
include,
loader: "ts-loader",
options: {
configFile: tsconfig,
transpileOnly: true
},
test: /\.tsx?$/
},
{
enforce: "pre",
exclude,
include,
loader: "source-map-loader",
test: /\.js$/
}
]
},
optimization: {
nodeEnv: "development"
},
output: {
filename: "[name].bundle.js",
path: path.join(__dirname, ...distDir),
publicPath: path.join(__dirname, ...distDir, "static/")
},
plugins,
resolve: {
extensions: [".js", ".ts", ".tsx", "*"]
},
target: "web"
};
export default webpackDevConfig;
My App.tsx:
import React, { SFC } from "react";
import ReactDOM from "react-dom";
const App: SFC = () => (
<div style={{ background: "red" }}>
<h3>test</h3>
</div>
);
My index.tsx:
import React from "react";
import ReactDOM from "react-dom";
import { App } from "./components";
ReactDOM.render(<App />, document.getElementById("app"));
// enables Hot Module Replacement (HMR)
if ((module as any).hot) {
(module as any).hot.accept("./components/App", () => {
// for HMR to work, `App` must be re-required
const NextApp = require("./components/App").default;
ReactDOM.render(<NextApp />, document.getElementById("app"));
});
}
My tsconfig.json:
{
"compilerOptions": {
"allowJs": true,
"jsx": "react",
"module": "commonjs",
...
}
}
The error itself seems to give the solution: You may need an appropriate loader to handle this file type., however, it is my understanding that ts-loader should be able to handle react.
Here is an example webpack.config provided by the ts-loader team used in an app that uses typescript and react. The set up is fairly similar to my own, however, I do not use webpack-dev-server, rather, I use webpack-dev-middleware.
The issue was resolved by niba's comment on the original question. It seems that ts-loader when given a single module to include will not traverse the linked modules. Removing the include field or using the folder name fixed this error for me.

WebPack loads all semantic-ui components

I'm currently working on a project and i need to configure WebPack. In the project, we are also using ReactJS and Semantic-UI. Here is webpack.config.js :
var path = require("path");
var webpack = require('webpack');
var BundleTracker = require('webpack-bundle-tracker');
var BundleAnalyzer = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
context: __dirname,
entry: {
react: ["react", "react-dom"],
home: './assets/js/index.jsx',
},
output: {
path: path.resolve('./assets/bundles/'),
filename: "[name].js",
},
plugins: [
new BundleTracker({filename: './webpack-stats.json'}),
new webpack.optimize.CommonsChunkPlugin({
names: ["react"],
}),
new webpack.optimize.CommonsChunkPlugin({
name: "home",
chunks: ['home'],
filename: "[name]-[hash].js",
}),
new BundleAnalyzer(),
],
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: { presets: ["es2015", "react"] }
},
],
},
resolve: {
modules: ['node_modules', 'bower_components'],
extensions: ['*', '.js', '.jsx']
},
};
In assets/js/index.jsx file, we just have these import statements :
import React from "react";
import ReactDOM from 'react-dom';
import { Button } from 'semantic-ui-react';
By running webpack command, it outputs two files:
react.js: 779 KB
home-[some_hash_number].js: 1.5 MB
Using webpack-bundle-analyzer plugin, we get this:
As you see the red rectangle in the picture, all of the semantic-ui react components are bundled into home.js file although i just imported Button component from in assets/js/index.js file and that's why the output file gets too big.
Is there any way to just bundle needed components?
UPDATE
Reading #Alexander Fedyashov answer, i installed babel-plugin-lodash and updated webpack.config.js accordingly:
var path = require("path");
var webpack = require('webpack');
var BundleTracker = require('webpack-bundle-tracker');
var BundleAnalyzer = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
context: __dirname,
entry: {
react: ["react", "react-dom"],
home: './assets/js/index.jsx',
},
output: {
path: path.resolve('./assets/bundles/'),
filename: "[name].js",
},
plugins: [
new BundleTracker({filename: './webpack-stats.json'}),
new webpack.optimize.CommonsChunkPlugin({
name: "react",
}),
new webpack.optimize.CommonsChunkPlugin({
name: "home",
chunks: ['home'],
filename: "[name]-[hash].js",
}),
new BundleAnalyzer(),
],
module: {
loaders: [
{
test: /\.jsx?$/,
exclude: /node_modules/,
loader: 'babel-loader',
options: {
plugins: ["lodash", { "id": ["lodash", "semantic-ui-react"] }],
presets: ["es2015", "react"],
}
},
],
},
resolve: {
modules: ['node_modules', 'bower_components'],
extensions: ['*', '.js', '.jsx']
},
};
Now everything is working and only needed components are loaded.
It should be splitted by Webpack, but in fact tree shaking doesn't work. You can use babel-plugin-lodash as described in SUIR docs.
You should keep in mind, that some of SUIR's components are dependent from each other, i.e.:
Button requires Icon and Label
Label requires Icon and Image
Image requires Dimmer
Dimmer requires Portal.
However, plugin will allow to strip such components as Rail, Reveal and Advertisement if you don't use them.
There is a new feature on Webpack 2 to solve this issue, read this article
https://medium.com/#adamrackis/vendor-and-code-splitting-in-webpack-2-6376358f1923

Resources