I'm migrating a web app from requireJS to webpack.
With requireJS, I have different configurations depending on the environment.
For live environment I use r.js to minify and bundle all of my
modules and their dependencies into a single file. Afterwards, I add
almondJS to manage the dependencies and then I load my js bundle like the following:
<script src="bundle.min.js"></script>
For my development environment, I Load requireJS like this:
<script src="require.js" data-main="/main-config"></script>
and requireJS will use my configuration file specified by data-main, to load modules and their
dependencies asynchronously
As you can see, with requireJS module loading and bundling are two separate processes and that allows me to debug AMD modules during development without needing sourcemaps
How can I achieve this scenario using webpack as a module loader only without bundling during development ?
If this is not possible, is there any other way I can see my source files in the browser debugger without generating sourcemaps?
How can I achieve this scenario using webpack as a module loader only without bundling during development ?
Webpack will always bundle, despite the envieronment.
If this is not possible, is there any other way I can see my source files in the browser debugger without generating sourcemaps?
If your code is transpiled/compiled, you'll need sourcemaps to see that. There is no way to workaround that.
It's true that if your code is transpiled then you'll need sourcemaps. But it is possible to get around bundling though. Yes, webpack will really always try to bundle, but with plugins the code can be taken out of the bundle and placed in the output directory as if it was simply run through the transpiler.
I have a node application that I want to simply transpile to ES5 file-by-file and not bundle anything. So my config to do that is roughly this:
let config = {
entry: [
glob.sync(srcDir + '/**/*.js') // get all .js files from the source dir
],
output : {
filename : '[name].rem.js', // webpack wants to bundle - it can bundle here ;)
path: outDir
},
resolve: {
alias: {
'app': appDir
}
},
plugins: [
new RemoveEmptyScriptsPlugin({extensions: ['js'], scriptExtensions: /\.rem\.js/}) // for all .js source files that get bundled remove the bundle .rem.js file
],
module: {
rules:[{
test: /\.jsx?$/,
type: 'asset/resource', // get webpack to take it out instead of bundling
generator: {
filename: ({filename}) => filename // return full file name so directory structure is preserved
},
use: {
loader: 'babel-loader',
options: {
targets: { node: 16 },
presets: [
['#babel/preset-env', { modules: 'commonjs' /* transpile import/export */}],
]
}
}
}]
}
};
// Since the code does not go through the full pipeline and imports are not getting resolved, aliases will remain in the code.
// To resolve them it takes to hack the aliases object into the babel config
config.module.rules[0].use.options.plugins.push(['babel-plugin-webpack-alias-7', {config: {resolve: {alias: config.resolve.alias}}}];
But then it appeared that the currently published babel-plugin-webpack-alias-7 does not support providing an Object to the config option so I had to patch the plugin https://github.com/shortminds/babel-plugin-webpack-alias-7/pull/22
Ah, and then the webpack-remove-empty-scripts plugin had an issue with my idea so I had to patch that too https://github.com/webdiscus/webpack-remove-empty-scripts/pull/6
Related
I'm next js for my project and it uses webpack 5 to compile typescript codes
I have several web worker scripts inside my public folder under path "/workers/**/*.worker.js"
I was wondering if I can write them in typescript too
or at least use babel to transpile them for es5 (for old browsers)
I know that anything under the "public" folder is served as is and as a file (like a CDN)
can I add a "workers" folder to my project and load them in the public path with webpack and next js?
thanks to #nalin-ranjan I've come up with the solution
in my "next.config.js" I added a rule to my webpack config:
module.exports = {
webpack: (config) => {
config.module.rules.push({
test: /\.worker\.ts$/,
type: 'asset/resource',
generator: {
filename: 'static/[hash:5].[name].js',
},
use: [
{
loader: 'ts-loader',
options: {
transpileOnly: true,
configFile: __dirname + '/worker.tsconfig.json',
},
},
],
})
return config
},
}
with this rule, I could require my workers and use them as URLs and transpile typescript
also, I had to add a new "tsconfig" that had "isolatedModules" option disabled (because web workers are not modules). for that, I created an identical tsconfig file to next.js but disabled isolatedModules. the reason being that next.js forbids you to disable isolatedModules and resets it back
I'm using Webpack to build my front end components.
I have some React components which need classic webpack bundling, though I also have some vanilla JS files.
Those latter files are independent, so they won't get imported from React files. From my understanding, they need to be defined as entrypoints, so that Webpack reads and processes them. So far, so good.
The trouble is that I'd like Webpack to load them with Babel, and that's all, only give me back the JS file processed through Babel, I'm not interested in a bundle for these files.
Is it possible to do that? Only get the result of the babel loader, and not produce a bundle for some entrypoints?
Maybe I shouldn't use Webpack at all for these files?
Or maybe I should just set these bundles as 'library' so that I can reach them from the HTML pages?
What do you think guys?
Thanks by advance ;)
depends on how easy it is to find these files. I have a project that has similar requirement. What I have done is:
1/ put the vanilla js file in third_party/lib/
2/ import/require them in my current project
3/ set up my webpack.config.js as follows:
module.export = {
module: {
rules: [{
test : /.js$/,
exclude : /node_modules|third_party/,
loaders : ['babel-loader' /* other loaders? */],
},{
test : /third_party.*?\.js$/,
use: [{
loader : 'babel-loader' // or other loaders
},{
loader: 'file-loader'
options: {
name : '[path][name].[ext]',
outputPath : 'dist/third_party'
}
}]
}]
}
}
oh, you will need to npm i --save-dev file-loader
edit: I should clarify that this will bundle the vanilla js file as separate files to your main bundle, so you will have to import them by script tags yourself in your html file. (or if they were worker files, called by your script)
I'm creating a javascript project. To create it I'm using gulp and babel.
My problem is that I can't develop my code over multiple file, so I'm search a solution to 'enable' importing. At the moment I'm trying to configure webpack.
The Gulp Task is this:
gulp.task('webpack', () => {
return webpack_stream(webpack_config)
.pipe(rename('webpack_code.js'))
.pipe(gulp.dest('.build/asset/webpack/'));
});
The webpack.config.js is this:
module.exports = {
entry: ['./src/asset/js/main.js'],
output: {
filename: 'bundle.js',
},
devtool: 'source-map',
module: {
rules: [
{
test: /\.(js)$/,
exclude: /(node_modules)/,
loader: 'babel-loader',
query: {
presets: [
['env', 'stage-0',{ modules: false }],
],
},
},
],
},
resolveLoader: {
modules: ['./node_modules'],
},
resolve: {
modules: ['./node_modules'],
},
target: 'node',
};
My current error is this:
Error in plugin 'webpack-stream'
Message:
multi ./src/asset/js/main.js
Module not found: Error: Can't resolve 'babel-loader' in ...
What's wrong?
Another Question: What's I have to put as value of entry key? Only the entry point js file or the whole files of the project?
Thanks!!
What's wrong?
I'd guess that in your project, your Webpack instance is not finding the babel loader because of your config / environment specific issues.
I've had the exact same issue as you. Here are some troubleshooting steps for to check first:
See if babel-loader is actually installed. I know it is simple, but it can save you time.
Check which Webpack/Babel versions you're dealling with in your package.json file. I'm using Webpack 4 and Babel 8. Sounds like some newer versions doesn't accept this: use: 'babel' in your webpack.config file. You need to ensure that the -loader is being used as it follows: use: 'babel-loader'.
Reinstall your node_modules folder. Sometimes it works.
Another Question:
What's I have to put as value of entry key?
Only the entry point js file or the whole files of the project?
Accordingly to Webpack's docs:
The entry object is where webpack looks to start building the bundle. The context is an absolute string to the directory that contains the entry files. - Webpack Ref
Considering that, you should pass to the entry object, the path of a folder or a file that will be used to generate your final JS file with all your modules in it.
If you have nested files, that you don't import as modules, I think you'll have to head to the docs and see this specific case.
But if this files are nested and are being imported as modules, in your entry file/folder, they will be generated in the output file.
I know it's not much but following these steps, helped me to solve it. :)
new to Webpack. I was thinking about migrating JS part of my application to it. However, I don't like the way it handles CSS. Would like to keep it easy and link them on my own. Unfurtunately documentation wasn't very helpful, same with the search results.
So, what do I need exactly?
Stylus compilation from lots of .styl files to static .css.
There will be three static stylesheet files (entry points?), but completely different from entry points of JS part of an application.
Also some "watch" feature, which would compile css when one of source .styl files has been changed.
Is there somebody who could point me in right direction, maybe write a config? Is this even possible with Webpack or should I stay with Grunt?
Thanks for any useful answer.
To learn more about the details of Webpack you can refer to this online book SurviveJS - Webpack, which will walk you through most of concepts related to Webpack.
To accomplish what you need you can start by creating webpack.config.js in the root of your project and it can be like this:
var ExtractTextPlugin = require('extract-text-webpack-plugin');
module.exports = {
entry: './entry.js', // you application entry point
output: {
filename: 'bundle.js', // resulting bundle file
path: './public' // the output folder path
},
module: {
loaders: [
{
test: /\.styl$/,
loader: ExtractTextPlugin.extract("style", "!css!stylus") // plugin used to extract css file from your compiled `styl` files
}
]
},
plugins: [
new ExtractTextPlugin('style.css') // output css bundle
]
};
Then require your stylus files in you entry.js file require('./style.styl');
Don't forget to install required loaders and plugins
npm install --save-dev css-loader sass-loader style-loader extract-text-webpack-plugin
I start to learn react js and they say on the react website "We recommend using React with a CommonJS module system like browserify"
So I used browserify with a simple hello world react component. Finally it produces an output file bundle.js of 651 ko (just for a simple hello world).
With this file bundle.js, I no longer have to include the scripts react.js and react-dom.js in my webpage, so I concluded that the file bundle.js includes my component and the react library.
But if I creates many components, I will have some javascript files and after the browserify transformation, each output files will be big because each files contains the react library. it will produce only one output file.
So I don't understand why they recommend to use browserify rather than just include react.js and react-dom.js library into my webpage and also my components js files after a babel transformation?
For development it is better not to minify. You apply minify when you go to production. For example with gulp;
gulp.task('appjs', function(){
browserify({ debug: true })
.transform(babel.configure({stage: 0}))
.require(source.appjs, { entry: true })
.bundle()
.pipe(vsource('app.min.js'))
.pipe(gulp.dest('./ui-dist'));
});
gulp.task('buildapp', function(){
browserify({ debug: false })
.transform(babel)
.require(source.appjs, { entry: true })
.bundle()
.pipe(vsource('app.min.js'))
.pipe(vbuffer())
.pipe(uglify())
.pipe(gulp.dest('./ui-dist'));
});
I think your question is about the size of the bundle file (the resulted file of browserify build), you worry about the time it will take when loaded on the page. This is some really important things you should know :
1. you don't have to include all your files in one bundle : you can generate multiple bundles. For example, you can configure browserify to create one bundle for your vendor files, and one or multiple bundles for your components.
in Dev mode, you don't have to minify your bundle,
For prod, you should generate your bundle using the react prod mode and minification.
To achieve point 1 (multiple bundles), here is an example with grunt browserify plugin.
var jsFiles = {
jsSrcFiles: './src/main/js/vs/**/*.js*', // my js and jsx source files
jsLibs: [
// vendor libs that I want to put in separate bundle
'react/addons',
...
]
};
...
browserify: {
app: {
options: {
transform: ['reactify'],
extensions: ['.jsx'],
// Here is where I tell browserify not to bundle vendor files with my source files
external: jsFiles.jsLibs
},
src: [jsFiles.jsSrcFiles],
dest: buildParams.js + '/vs_app.js'
},
// here is where I build vendor files in separate bundle named vendor.js
vendor: {
src: ['.'],
dest: buildParams.js + '/vendor.js',
options: {
alias: jsFiles.jsLibs
}
}
}...
Browserify is a great tool when it comes to small projects, when your project becomes more complex, browserify config tends to be very complex. In order to have more control of your built bundles, I recommend to use webpack, which is also a tool that facebook recommends. It allows easy bundling customization...