Webpack gzip compressed bundle not being served, the uncompressed bundle is - javascript

I am trying out Webpack for the first time. I've been using Gulp with Browserify for some time and am pretty comfortable with it. At this point, I'm just testing out a couple of Webpack plugins. Namely the compression-webpack-plugin. I've never used compression before, so bear with me if I'm making any noob mistake.
Below is my webpack.config.js. The result is I get a main.js, main.js.gz, main.css and index.html. The main.js is injected into the index.html, but if I open index.html in my browser, it serves the uncompressed main.js, not the compressed main.js.gz. I had read that I wouldn't need to include the .gz extension in my script tag, and the html-webpack-plugin doesn't include it, so I figured things are working correctly, yet the uncompressed main.js is served, rather than the compressed one.
var path = require('path');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var CompressionPlugin = require('compression-webpack-plugin');
module.exports = {
entry: './app/scripts/main.js',
output: {
path: path.join(__dirname, 'public'),
filename: '[name].js',
chunkFilename: '[id].js'
},
module: {
loaders: [
{test: /\.scss$/, exclude: /node_modules/, loader: ExtractTextPlugin.extract('style-loader', 'css-loader!sass-loader')},
{test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader'}
]
},
plugins: [
new HtmlWebpackPlugin({
hash: true,
template: 'app/index.html',
inject: 'body'
}),
new ExtractTextPlugin('[name].css'),
new CompressionPlugin()
]
};

To load main.js.gz instead of main.js in case of included main.js in script-tag, you need to configure your web-server (apache, nginx, etc.)
Remember that configuration should load .js.gz or .js depend on if browser accepts gzip. Web-server can check it in HTTP request header Accept-Encoding: gzip, deflate
In browser devtools you will see main.js in any cases.

You can conditionally serve gz statics easily with nginx gzip static module. The server checks if app.js.gz file for e.g. requested /statics/app.js is present and serves it transparently. There is no need to change your application or detect Accept-Encoding - all that is handled by nginx module. Here is config snippet:
location /statics/ {
gzip_static on;
}

I'm a little late to this thread, but thought I'd add my 2c. I generated a gz file using webpack, but Apache kept serving the uncompressed one (or erroring if it wasn't present), despite Accept-Encoding being set correctly. Turns out I had to uncomment AddEncoding x-gzip .gz .tgz and reload httpd. For the record, AddType application/x-gzip .gz .tgz was already set, and I'm using Apache 2.4.6 with Chrome 62. Thanks to Dmitry above for nudging me to look at my conf/httpd.conf file.

Related

Do I need to generate br and gz files for s3 and cloudfront?

When I build my application using vue cli and webpack, I add two plugins:
new CompressionPlugin({
filename: '[path].gz[query]',
algorithm: 'gzip',
test: /\.(js|css|html|svg)$/,
threshold: 8192,
minRatio: 0.8,
}),
new BrotliPlugin({
//brotli plugin
asset: '[path].br[query]',
test: /\.(js|css|html|svg)$/,
threshold: 10240,
minRatio: 0.8,
}),
These plugins creates br and gz file for each files webpack create. for example app.css:
app.a35d9d23.css
app.a35d9d23.css.gz
app.a35d9d23.css.br
Now I moved to serve the application in cloudfront and s3.
My question is do I need to generate those files and upload them to s3? or cloudfront and s3 know to serve themselves (they creates br/gz files)?
You shouldn't generate the gz and br files, CloudFront won't use them. These files are useful when you use a webserver (apache, nginx) as they can be optimized to serve the precompressed files instead of compressing them on the fly.
When you use CloudFront, you can enable compression which automatically takes care of serving compressed files. There are some caveats though, like there is a file size limit and it only supports gzip, but on the other hand it's just a checkbox you turn on.

How to serve cdn links for assets in NuxtJS?

I am working on a NUXTJs to create server side rendered website. My question is that although there is a assets/static folder in nuxt project structure to serve images & static files, i want to set cdn link for all my image source.
What would be the best approach to do that?
Possible ways I can think of:
Vuex Store - set baseURL for the images and then use in components
env - use environment variable to set the cdn URL
TIA
You can set it via publicPath property in nuxt.config
export default {
build: {
publicPath: 'https://cdn.nuxtjs.org'
}
}
https://nuxtjs.org/api/configuration-build/#publicpath
If you have a team working on the project, use Vuex. It save the baseURL in the project itself. Less hassle to copy/share the env variables to the team.
Alright after spending a couple of hrs, As answered above you can set cdn url to nuxt.config.js file. If you are someone like me who is using CloudFront / S3 bucket, After npm run build. you can create nuxt folder to your s3 bucket and upload everything from .nuxt/dist/client to this folder. the public path looks as follows in nuxt config file
build: {
publicPath: 'https://your-cdn-url.net/nuxt'
}
But for PWA,manifest.json file it is important that the manifest is served from the same domain, and not from the CDN.so you'll have to override the public path.you can find more info here
I'm using nuxt 2.15,syntax has to be exactly like as follows. nuxt.config.js
modules: [
[
'#nuxtjs/pwa',
{
workbox: { publicPath: '/_nuxt/' },
manifest: { publicPath: '/_nuxt/' },
},
],
],
3rd issue that I faced was, I've created categories.json file and uploaded to s3 bucket and was calling from axios, to avoid any cors issue update s3 cors setting as follows
You can find this in s3 bucket -> Permissions then -> scroll below -> () Cross-origin resource sharing (CORS)
[
{
"AllowedHeaders": [
"*"
],
"AllowedMethods": [
"GET",
"HEAD"
],
"AllowedOrigins": [
"*"
],
"ExposeHeaders": [],
"MaxAgeSeconds": 3000
}
]

Webpack trying to load build.js from subdirectory

I'm setting up a basic vue app with vuetify/vue-router, and when loading the base url '/', everything works fine. I can click a to /manage/products without any problem.
However, when loading /manage/products directly by typing in the address bar, I get this error:
Failed to load resource: the server responded with a status of 404 (Not Found)
It seems to want to load /manage/dist/build.js instead of /dist/build.js.
Can I change my webpack.config.js to make sure the right build.js is called?
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'build.js'
},
resolve: {
extensions: ['.js', '.vue'],
alias: {
'#' : path.resolve(__dirname, './src'),
'vue$': 'vue/dist/vue.esm.js',
'public': path.resolve(__dirname, './public')
}
}
vue-router 'hash' mode works, but I would like to use 'history' mode for cleaner URLs.
For reference: I've used this template
vue init vuetifyjs/webpack-simple
EDIT:
I've found the solution.
The vuetifyjs/webpack-simple template had a misconfiguration from the start.
Inside index.html I've changed:
<script src="./dist/build.js"></script>
to
<script src="/dist/build.js"></script>
And made sure that these options were present inside webpack.config.js:
devServer: {
historyApiFallback: true
},
vue-router 'hash' mode works, but I would like to use 'history' mode for cleaner URLs
The point of the History API is to allow you to map DOM-generated and server-generated pages onto each other.
This means that if JavaScript fails for any reason, then the server can deliver the page instead. This means that if someone deep links to a page on your site, then the server can just deliver that page (as opposed to delivering the homepage, and then using JavaScript to mutate it into the desired page).
You need to write server-side code that will deliver the page.

Bundled file is not found

I am using Golang (Echo) for my backend and React for my frontend. When I bundle my code using webpack, the file is created; however, I am getting an error in my console when I go to localhost:3000 stating the bundle file cannot be found. This is the exact error message: GET http://localhost:3000/build/app.bundle.js net::ERR_ABORTED.
Here is my server:
func main() {
env.SetEnvVars()
e := echo.New()
e.File("/", "server/static/index.html")
e.Logger.Fatal(e.Start(os.Getenv("PORT")))
}
Here is my webpack.config.js file:
module.exports = {
entry: './client/main.jsx',
output: {
path: path.resolve(__dirname, 'server/static/build'),
filename: 'app.bundle.js'
},
...
And the script tag in my index.html file is:
<script src="./build/app.bundle.js"></script>
The directory path regarding these files is currently:
/
server/
main.go
static/
index.html
build/
app.bundle.js
Any help would be appreciated!
The echo server you've set up only serves one single path, the root path ("/"), by rendering the contents of the index.html file. Because you haven't set up any other handlers for that server, any request to a path other than the root will result in 404, including those requests made from the index page via script and link tags, e.g.; <script src="./build/app.bundle.js"></script>.
To be able to serve a request to a path like "/static/build/app.bundle.js" for example you need to tell the server how to do that by registering a new handler.
With the echo server you can use its Static method to do that.
e.Static("/static", "static")
Please keep in mind that the links you use in html tags, the location of the corresponding files on your machine, and the location from where you launched your app matters if you use relative paths like ./build/app.bundle.js, and because of that the two arguments to e.Static may need to be somewhat different from the example here.
Here's a bit more info.

webpack watch doesn't trigger

I run webpack with native file system (inotify) support,
also tested with chokidar and it correctly picked up all changes to files on that filesystem/folder.
The webpack configuration in Sage 9 WordPress base theme is used (https://github.com/roots/sage/blob/c21df9965ff8217c3b4ff90bbe6099206d7b4fbf/resources/assets/config.json#L16).
Only the PHP files are listed for being watched on - but their dependencies (SCSS/JS/...) are also watched?
I start webpack watch with npm/yarn package script that starts webpack with
$ webpack --hide-modules --watch --config resources/assets/build/webpack.config.js
Webpack is watching the files… [BS] [HTML Injector] Running... [BS] Proxying: http://dev:8084 [BS] Access URLs: ---------------------------------- Local: http://localhost:3000 External: http://127.0.0.1:3000 ---------------------------------- UI: http://localhost:3001 UI External: http://127.0.0.1:3001 ---------------------------------- [BS] Watching files...
However, changing files - even just the PHP files specified in watch array above - doesn't trigger any update by webpack.
What config could be missing? Are there any ways finding out what exactly is webpack watching - and whether it really detects a change (and just ignores it) or not?
The reason was CORS, the script that should load new webpack builds is blocked by browser due to CORS restrictions. It is possible to configure browserSync to send proper headers for CORS, also see https://discourse.roots.io/t/sage-9-browsersync-not-loading-any-css-at-all-on-yarn-run-start/11332/26 .
new BrowserSyncPlugin({
target,
open: config.open,
proxyUrl: config.proxyUrl,
watch: config.watch,
delay: 500,
advanced: {
browserSync: {
cors: true,
},
},
}),

Categories

Resources