"webpack" vs "webpack --watch" creates different output - javascript

Im using this set up as the base of my project: https://www.typescriptlang.org/docs/handbook/react-&-webpack.html
When I run webpack, it compiles a bundle that works in the browser.
When I run webpack --watch, it re-compiles on file change, but causes this error in the browser:
Uncaught ReferenceError: exports is not defined
I looked at the output of both, and it looks like webpack --watch does not include the webpack bootstrap code or my modules - only the entry file transpiled.
webpack
Includes all of my modules in a single file, along with using webpacks own module require.
E.g: var io = __webpack_require__(20);
webpack --watch
Only includes my entry module - no other modules, no __webpack_require__.
E.g. var io = require("socket.io-client");
Versions:
- webpack: 3.7.1
- tsc: 1.8.10
module.exports = {
entry: "./src/index.tsx",
output: {
filename: "bundle.js",
path: __dirname + "/dist"
},
// Enable sourcemaps for debugging webpack's output.
devtool: "source-map",
resolve: {
// Add '.ts' and '.tsx' as resolvable extensions.
extensions: [".ts", ".tsx", ".js", ".json"]
},
module: {
rules: [
// All files with a '.ts' or '.tsx' extension will be handled by 'awesome-typescript-loader'.
{ test: /\.tsx?$/, loader: "awesome-typescript-loader" },
// All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'.
{ enforce: "pre", test: /\.js$/, loader: "source-map-loader" }
]
},
// When importing a module whose path matches one of the following, just
// assume a corresponding global variable exists and use that instead.
// This is important because it allows us to avoid bundling all of our
// dependencies, which allows browsers to cache those libraries between builds.
externals: {
"react": "React",
"react-dom": "ReactDOM"
}

The fix is to remove outDir from tsconfig.json:
{
"compilerOptions": {
"outDir": "./dist/"
}
}
It was the tsconfig.json file having a conflicting output directory. Files are only written by typescript when using webpack --watch

Related

Electron-Typescript: Bundling everything

I'm trying to create a web app using electron written in Typescript. I'm having problems when building my application. Specifically, I am not sure on how to combine: tsc (To convert my .ts file to .js) and then electron dist/main.js. Potentially, I want to run npm start which first compiles my .ts file and then run electron. Can anyone comment on what would be the best approach to achieve this?
Use ts-loader with webpack to bundle .ts files with config like below,
const path = require("path")
module.exports = {
entry: './src/index.ts',
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/
}
]
},
resolve: {
extensions: [ '.tsx', '.ts', '.js' ]
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
and then in your npm script include these,
{
"build-watch": "webpack -w",
"electron": "electon dist/main.js"
}
then start both using npm-run-all (or any other tool like concurrently),
npm-run-all start build-watch electron
I would suggest using https://webpack.electron.build/. It has instructions for adding typescript support here https://webpack.electron.build/add-ons#typescript

What's the difference between tsconfig's 'outFile' and webpack config's 'output'

What's different between the 'output' path? Is tsconfig is a loader? And webpack to resolve '.ts' file after the run tsconfig build?
Why the file 'src.js' is not found? It is deleted by webpack automatically?
tsconfig.json:
{
"compilerOptions": {
"module": "amd",
"noImplicitAny": true,
"removeComments": true,
"preserveConstEnums": true,
"outFile": "src.js",
"sourceMap": true
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules"
]
}
webpack.config.js:
module.exports = {
entry: './index.ts',
output: {
filename: './dest.js'
},
module: {
loaders: [{
test: /\.ts$/,
loader:'ts-loader'
}]
},
resolve: {
extensions: ['.webpack.js', '.web.js', '.ts', '.js']
}
}
When I run 'webpack' the 'src.js' is not found and 'dest.js' is ok.
Thanks a lot.
outFile
This configuration option is used by TS compiler when using tsc command to
Concatenate and emit output to single file.
You can read more about compiler options here.
output
This configuration option is used by Webpack to
The top-level output key contains set of options instructing webpack
on how and where it should output your bundles, assets and anything
else you bundle or load with webpack.
Why src.js is missing
When you use ts-loader instead of a tsc as part of webpack built, the outFile option from tsconfig.json is not used. Webpack when loading a .ts file detects that it should be passed to ts-loader, which in turn uses a compiler to compile only this one file and then returns output to a webpack. It never works with all files the way tsc does. That's why no src.js is generated.

Webpack concatenate scss files

In my last project I used gulp to concat all .scss files from several folders into one .scss file. Next I was using sass to compile that singe .scss file into css.
gulp.task('styles', function () {
gulp.src('styles/**/*.scss')
.pipe(concat('style.scss'))
.pipe(gulp.dest('production/'))
.pipe(sass({outputStyle: 'expanded'}))
.pipe(gulp.dest('production/'))
.pipe(sass({outputStyle: 'compressed'}))
.pipe(rename('style-min.css'))
.pipe(gulp.dest('production/'));
});
Now I want to create exactly the same 'building process' with Webpack.
entry: {
"style": "./styles/**/*.scss",
"style.min": "./styles/**/*.scss"
},
output: {
path: __dirname,
filename: "[name].css"
},
plugins: [
new ExtractTextPlugin('[name].css')
],
module: {
loaders: [
//Sass file
{ test: /\.scss$/, loader: ExtractTextPlugin.extract('css!sass') }
]
}
Unfortunately Webpack don't understand ** and *.scss. Is there any solution to gain the same behavior?
PS I need to concat those files. I don't want to use any kind of Sass #imports etc.
For example, you could use node-glob package like this:
var glob = require('glob');
var styles = glob.sync('./styles/**/*.scss');
module.exports = {
entry: {
'style': styles,
...
You need to use loaders for all file types except javascript, to load using webpack. In your case you need sass-loader, css-loader, style-loader. Perform the below steps to make your scss work using webpack:
Install below dependencies
npm install sass-loader css-loader style-loader
Add the webpack.config.js
Webpack config
module.exports = {
module: {
loaders: [
{
test: /\.scss$/,
loaders: ["style", "css", "sass?config=otherSassLoaderConfig"]
}
]
},
otherSassLoaderConfig: {
}
};
Now just require your scss file as require('./style.scss') and it will be loaded
For a detailed refrence you can also take a look at: https://stackoverflow.com/a/26876311/3878940

How to load library source maps using webpack?

I'm building two projects with webpack; one is a library for the other.
Is it possible to consume the sourcemaps from my library project when building my wrapper project? I would like the ability to debug my library code from my wrapper UI.
My build works correctly in that the library is built in. The only issue is sourcemaps. The JavaScript I see in the browser debugger is uglified, because sourcemaps are unavailable.
Snippet of my project structure:
+-- my-ui/
+-- dist/
+-- my-ui.js
+-- my-ui.js.map
+-- node_modules/
+-- my-lib/
+-- dist/
+-- bundle.js
+-- bundle.js.map
Snippet from webpack.config.js:
module.exports = {
entry: './src/js/main.jsx',
output: {
path: path.join(__dirname, 'dist'),
filename: 'my-ui.js',
library: 'my-ui',
libraryTarget: 'umd'
},
devtool: 'source-map',
module: {
loaders: [
{test: /\.jsx?$/, loader: 'babel', include: path.join(__dirname, 'src')}
]
},
plugins: [
new Clean('dist'),
new HtmlWebpackPlugin({
template: 'src/index.html',
inject: true
})
]
};
I finally figured out my issue...
Thanks to #BinaryMuse for the tip on source-map-loader. This indeed was the right way to go, though it wasn't working for me initially.
What I eventually realized is that I need to enable the source-map-loader for webpack in both "my-lib" and "my-ui". Without source-map-loader in "my-lib" webpack config, the source-map-loader inside "my-ui" errors (with a warning message sadly) because it cannot locate source maps for transitive dependencies of "my-lib". Apparently the source maps are so good that source-map-loader is able to peek at all aspects of the dependency tree.
Also of note, I ran into an issue using source-map-loader in conjunction with react-hot-loader. See, react-hot-loader does not include source maps. When source-map-loader tries to find them (because it's just scanning everything), it cannot and aborts everything.
Ultimately, I'd like source-map-loader to be more fault tolerant, but when set up correctly, it does work!
devtool: 'source-map',
module: {
preLoaders: [
{test: /\.jsx?$/, loader: 'eslint', exclude: /node_modules/},
{test: /\.jsx?$/, loader: 'source-map', exclude: /react-hot-loader/}
],
loaders: [
{test: /\.jsx?$/, loader: 'raect-hot!babel', exclude: /node_modules/}
]
}
My answer is similar to #Jeff Fairley's and I had the same directory structure, with the only difference being that I was using module: { rules: [] } instead of his module: { preLoaders: [..], loaders: [...]}. This is what I had to add to my webpack.config.js file:
mode: 'development',
devtool: 'eval-source-map',
module: {
rules: [
{
test: /\.js$/,
enforce: "pre",
use: ["source-map-loader"],
}
]
},
Then I ran
npm i -D source-map-loader
and I saw the TypeScript source code of the dependency I was using when clicking through tracebacks in Chrome's devtools. See the Webpack docs for source-map-loader.
I am using create-react-app and this is how I Fixed it (without running eject cmd)
Note : If your app is already overriding webpack config using react-app-rewired you can ignore first three steps.
npm i react-app-rewired -D - This will help you to override webpack
configuration.
package.json - change your scripts, replace react-scripts with react-app-rewired
"scripts": {
"start": "react-app-rewired start",
"build": "react-app-rewired build",
"test": "react-app-rewired test",
"eject": "react-app-rewired eject"
}
config-overrides.js - create this file in the parent level of the app.
npm i source-map-loader -D - To load source maps (assuming that your lib's dist has source map file). It doesn't matter which build tool(ex: Rollup, webpack or parcel) you use to generate sourcemap.
Copy below code in config-overrides.js
module.exports = {
webpack: (config, env) => {
// Load source maps in dev mode
if (env === 'development') {
config.module.rules.push({
test: /\.(js|mjs|jsx|ts|tsx)$/,
use: ['source-map-loader'],
enforce: 'pre',
});
// For `babel-loader` make sure that sourceMap is true.
config.module.rules = config.module.rules.map(rule => {
// `create-react-app` uses `babel-loader` in oneOf
if (rule.oneOf) {
rule.oneOf.map(oneOfRule => {
if (
oneOfRule.loader &&
oneOfRule.loader.indexOf('babel-loader') !== -1
) {
if (oneOfRule.hasOwnProperty('options')) {
if (oneOfRule.options.hasOwnProperty('sourceMaps')) {
// eslint-disable-next-line no-param-reassign
oneOfRule.options.sourceMaps = true;
}
}
}
});
}
return rule;
});
}
return config;
},
};
Restart your app (if it's already running). source files get loaded in different locations, based on path in map file. Check all folders patiently :)
Note :
1. Your source maps get loaded in one of the folder(ex : localhost:3000 or webpack:/// ) based on path it reads from xxx.js.map file.
2. If you are using rollup for your libs, please make sure you give proper path in the configuration file (output.sourcemapPathTransform ), This will help to load sourcemaps in the proper location.
You should be able to use any of the eval source map options that Webpack provides.
Really that just amounts to setting the right devtool option in your webpack.config.js for the my-lib project.
devtool: 'eval',
eval and eval-source-map should both work.
See the Webpack documentation for the various options.

Webpack: node_modules/css/index.js didn't return a function

I'm trying out webpack for the first time and used this tutorial to get started and include react.js.
After finishing the steps and installing the style and css module I keep getting an error that the css module didn't return a function.
This is my index.jsx:
/** #jsx React.DOM */
'use strict';
require('../css/normalize.css');
var React = require('react');
var Hello = require('./Test/Hello');
React.render(<Hello />, document.getElementById('content'));
And my webpack config file:
module.exports = {
entry: './ui/src/index.jsx',
output: {
path: __dirname + '/build-ui',
filename: 'app.js', //this is the default name, so you can skip it
//at this directory our bundle file will be available
//make sure port 8090 is used when launching webpack-dev-server
publicPath: 'http://localhost:8090/assets'
},
module: {
loaders: [
{
//tell webpack to use jsx-loader for all *.jsx files
test: /\.jsx$/,
loader: 'jsx-loader?insertPragma=React.DOM&harmony'
},
{
test: /\.css$/,
loader: "style!css"
},
{
test: /\.scss$/,
loader: "style!css!sass"
}
]
},
externals: {
//don't bundle the 'react' npm package with our bundle.js
//but get it from a global 'React' variable
'react': 'React'
},
resolve: {
extensions: ['', '.js', '.jsx']
}
};
When webpack tries to bundle the project it always states the following error:
ERROR in Loader /Users/Johannes/Documents/Development/holmes/node_modules/css/index.js didn't return a function
# ./ui/src/index.jsx 5:0-31
I don't know what to do about that. Has anyone encountered that issue? And how can I solve it?
EDIT: My directory looks as follows:
holmes/
ui/
css/
normalize.css
src/
Test/
Hello.jsx
index.jsx
index.html
package.json
webpack.config.js
This error is caused by a css module inside node_modules. Since you've specified the css-loader in your config, webpack tries to lookup that loader inside node_modules and finds another module called css which doesn't look like a loader (hence the error message).
To avoid confusion you should simply add the -loader postfix to each loader. Omitting the -loader postfix is just a convenience feature by webpack, but unfortunately it's the culprit of that error in your case.
loaders: [
{
//tell webpack to use jsx-loader for all *.jsx files
test: /\.jsx$/,
loader: 'jsx-loader?insertPragma=React.DOM&harmony'
},
{
test: /\.css$/,
loader: "style-loader!css-loader"
},
{
test: /\.scss$/,
loader: "style-loader!css-loader!sass-loader"
}
Update: Starting with webpack 2, you can't omit the -loader postfix anymore. We decided to do this to prevent errors like this.
I had a similar issue with react-flexbox-grid. In my case, the solution was installing css-loader and style-loader npm modules:
npm install css-loader style-loader --save-dev
I also came across a similar issue using node-noop.
Fortunately, using null as a replacement worked when I added enzyme and react-addons-test-utils to a project.

Categories