Handling cache beyong Nginx server and webpack js and css versioning - javascript

I have a React nodejs app running on EC2.
I have set up 3 instances of it beyond Nginx for the load balancing.
I have also enabled cache in the Nginx configuration.
Basically everything should be cached beside different versions of app.js which holds the bundled React code and style.css which is also bundled.
I would like to add a version number in the js and css src link (e.g http://mywebsite.com/app.js?1.0)
My question is, can I automate this operation with webpack? Is this the way to go?

html-webpack-plugin is your friend here.
Instead of creating your index.html file, allow webpack to do it for you.
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: "./index.js",
output: {
filename: "./dist/app.bundle.[hash].js"
},
plugins: [
new HtmlWebpackPlugin({
hash: true,
filename: './dist/index.html'
})
]
}
This will add the output script into index.html automatically and will generate a hash for the file.

Related

Unable to communicate with my chrome extension's javascript file after bundling my extension with webpack

I tried using firebase on my chrome extension for authentication, and I was getting error regarding
Uncaught SyntaxError: Cannot use import statement outside a module
After searching, I was told that I will need to bundle my app to be able to use import statement
On installing webpack, configuring and running npm run build, my service_worker and content script lost communication with my popup.js file. all messages sent into the file do nothing.
Here is my webpack.config.js settings
const path = require('path');
module.exports = {
// The entry point file described above
entry:{
background: './background.js',
content: './index.js'
},
// The location of the build folder described above
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].js',
},
// Optional and for development only. This provides the ability to
// map the built code back to the original source format when debugging.
devtool: 'eval-source-map',
};
index.html link to javascript file
<script src="./dist/content.js"></script>
Please what am I doing wrong? this is my first time to both using webpack and configuring chrome extension.
NOTE: my index.html is declared as web_accessible_resource file and injected into the webpage using iframe. just to give more context to the question.
this is how I was able to resolve the problem.
I added both my popup.js and background.js file to the entry object of my webpack.config.js and replace the original file path with the path to the compiled files. my files now look like this
webpack.config.js
module.exports = {
//...
entry: {
background: './background.js',
index: './index.js',
},
//...
manifest.json
//...
"background": {
"service_worker":"./dist/background.bundle.js" //path to webpack bundled service worker file
},
//...
index.html
<script src="./dist/index.bundle.js"></script> <!--path to bundled popup javascript file--->

Set up webpack to pull JS file from local rather than via HTTP

webpack.config.js pulls remote js for Module Federation.
plugins: [
new ModuleFederationPlugin({
remotes: {
'mfe1': "mfe1#http://xxxxxxxxxx.com/remoteEntry.js"
}
})
],
How can I use a local JS file in remotes or in addition to remotes? I have a simple react.js library in the other folder, with ./dist/browser/remote-entry.js file in it. I cannot publish to npm, so I'm trying to load it from local. Would it be something like:
plugins: [
new ModuleFederationPlugin({
remotes: {
'mfe1': "../../myproject/dist/browser/remoteEntry.js"
}
})
],
The remotes entry is supposed to be a url that is accessible during run-time, not build-time. If it was only necessary during build-time, it would automatically imply that the remoteEntry gets bundled, which defeats the purpose of Webpack Module Federation (WMF for short).
You say:
webpack.config.js pulls remote js for Module Federation.
But I'm not sure what that is supposed to mean. Webpack does not "pull" the remote files at all. It tells the final build where to look, so that when your code (i.e. bundle.js) actually executes, it knows from where to load modules dynamically.
This means that, in order for WMF to work, you still need to serve the file from your web server.
You primarily have two choices:
If you don't want dynamic loading of modules, just build your project without WMF.
If you do want dynamic loading, then you need to tell webpack that remotes url. Ideally, you can get the actual server address from process.env, which you can provide via dotenv (or through many other means):
webpack.config.js
// ...
module.exports = {
// ...
plugins: [
new ModuleFederationPlugin({
remotes: {
'mfe1': `mfe1#${process.env.REMOTE_HOST || 'http://localhost:8080'}/remoteEntry.js`
}
})
],
// ...
};
.env
REMOTE_HOST=http://xxxxxxxxxx.com
Also, you might want to consider this article on how to deploy a WMF build.

Combine, Minify, and convert to ES5 with WebPack and Babel

I have a project that works perfect and was written in TS, I had to convert it to plain JS and it works for the most part. The issue where I am struggling is removing the default WebPack loader after the files have been combined and minified, WebPack includes a loader to the final output even thought I do not need a loader since all the files are combined into one large file.
+ filea.js
+ fileb.js
+ filec.js
+ filed.js
-> output bundle.js
I have read a few articles/posts that recommend manually creating a config file providing the name of each of the files that will combined and minified, this may work OK but the problem is that the project I am working on is broken into small chunks (modules) so that tools such WebPack can be smart enough and know when a file should be added as a dependency in the final output.
I know we can combine and minify multiple individual JS files but when it comes to exporting a single file it seems like the task is trivial With TS but in the vanilla JS world there is little or no information about the subject.
I don't understand something, do you want to have one big file or small individual modules (chunks)?
An example of small modules:
module.exports = {  
entry: {    
app: './src/app.js',
admin: './src/admin.js',
contact: './src/contact.js'  
}
};
Another method is one main module and it contains all smaller modules.
module.exports = {  
entry: {    
app: './src/app.js'  
}
};
You can also use something like lazy loading. Then the modules (chunks) will be dynamically loaded only when needed. lazy-loading
Here is an example of using several entries webpack-boilerplate.
Sounds like you have a project with several JS files and you want to use webpack to bundle all of them and minify the result.
Webpack was built for this.
You'll need to add a build step in your package.json like this:
"scripts": {
"build": "webpack --config prod.config.js"
}
Then you'll need to create a webpack.config.js with a module.exports block that has an entry point and rules to include in your project. The following should be a minimal setup that can get your started:
const path = require('path');
module.exports = {
entry: "./your/path/to/src",
output: {
path: path.resolve(__dirname, "dist"),
filename: "bundle.js"
},
module: {},
plugins: [
new MinifyPlugin(minifyOpts, pluginOpts)
]
}
You can add modules that perform additional code transpilation for files that matcha a certain regex. You can also use a plugin to perform minification such as babel-minify-webpack-plugin as documented here https://webpack.js.org/plugins/babel-minify-webpack-plugin/. (Note you will need to add this dependency.)
The full webpack configuration can be found here: https://webpack.js.org/configuration/

webpack load AMD modules without bundling

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

Using Webpack and stylus to create static css

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

Categories

Resources