Webpack - How to require result file in base html (best practice) - javascript

I just started using Webpack for my SPA and I have a question. How do I require the result bundle/file in my HTML? Should I just use the tag or is there a better practice for this?

You can automatically include all JavaScript and CSS bundles using HTML Webpack Plugin.
Example
To install the plugin you need to run npm install html-webpack-plugin --save-dev in your project directory.
In the following example plugin will read source HTML file and automatically append available CSS files in head and all JavaScript bundles just before the end of body. It plays nicely with ExtractTextPlugin. If you have more bundle chunks, they'll be appended appropriately as well.
As a bonus you can use any template engine if you want to dynamically change or generate parts of your HTML file. Out of the box it supports EJS template engine with possibility to use any other via loaders.
var webpack = require("webpack");
var HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/js/entry', // Source JavaScript file
output: {
path: './bin/', // Output directory
filename: "./js/bundle.js" // Result JavaScript file
},
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html', // Source HTML file
filename: './index.html' // Result HTML file
}),
]
};
It's worth noting that HTML Webpack Plugin have a lot of features to play with, including minifying, filtering chunks, adding file hash to URLs to prevent caching... You can learn about those and many more in documentation.

You can look my starter seed with angular2 + webpack. All files has been in build directory(app.js, vendor.js, polyfills.js) + maps
Link to webpack.config.js

Webpack is a module bundler. It will bundle your entire SPA in a single or multiple javascript bundles according to your webpack configuration. Now we need to import these js bundles inside our HTML code and the only way to insert those things in our HTML is to use script tag. So you import them in your html like this :
<script src="bundle.js"></script>
So yes, this is the best practice.

Related

Nuxt (and Webpack): How to separate a single JS file to be reused by external app?

I've stumbled upon several pages about importing external files into a Nuxt project, but what I'm trying to do is the opposite.
I have two sites or apps: Site A and Site B. Site A is the main one built using Nuxt. Site B is a simple site with static pages, not using Nuxt or Vue.
Site A has a JavaScript file, let's say its path is /lib/common.js. I use it extensively on Site A. And I also want to use it on Site B.
However, when I do yarn generate on Site A, all my JS files, including common.js, get bundled into a JavaScript chunk files, and each file is named with a hash of the content of the file. For example, /lib/common.js, /lib/util.js get bundled up as /dist/_nuxt/05443d2eb25fc282bbea.js while /lib/user.js is bundled as /dist/_nuxt/1326d0fc90870f9f4ca4.js.
That means:
the file I want to use is actually bundled with other files into the same package, so if I load that file, I have to load extra code with it and,
I can't really predict the name of that file.
Is there a way for me to tell Nuxt, or most likely Webpack, to single out /lib/common.js into its own bundle and then save it as /dist/_nuxt/lib/common.js instead of a hash, so the filename is more predictable?
You would need to create a separate webpack configuration for that single file to achieve the desired result as only one output configuration per configuration file is supported[0].
[0] https://github.com/webpack/docs/wiki/configuration#output
Example common library configuration common.lib.config.js
var path = require('path');
module.exports = {
entry: './lib/common.js',
output: {
path: path.resolve(__dirname, 'dist/_nuxt/lib'),
filename: 'common.js'
}
};
And build it with webpack --config common.lib.config.js

Webpack Including JavaScript File via <script> Tag

I'm using Webpack with Storybook and need to include a JavaScript library file in an HTML file via a script tag. Unfortunately, I get a 404 error indicating that the file was not found (the file's path is based on my local filesystem and is correct). How do I inform Webpack regarding where to look for my library or "static" files?
Add files in entry object in webpack.config.js
entryPoint = {
app: ['path/to/script', 'path/to/script2','./index.js'],
};
This will make sure that you have the library loaded when you have run index.js (entry point of project).
More on Webpack entry points.

Extracting a javascript file from webpack build

I am using webpack for a project where I need to have a javascript config file as part of the built files, but I cannot figure out how to do that.
So I need to have these files in the output:
index.html
app.js
config.js
I figure I need to either:
1) Copy the config.js file from the source folder to the build folder with CopyWebpackPlugin, or
2) Include the file in the compiled bundle and then extract it with ExtractTextWebpackPlugin.
I have tried dozens of different ways of configuring this, but when trying with the copy method, I get the file both inside the app.js bundle AND as a separate file. When I try with the extract method, I cannot seem to figure out how to extract javascript from the main bundle. The docs all seem to explain how to extract css.
How would I go about something like this?
You should be able to accomplish this by using multiple entry points.
https://webpack.js.org/concepts/entry-points/
entry: {
main: './path/to/file/app.js',
config: './path/to/file/config.js'
}
output: {
filename: 'output/path/[name].js'
}
A more complex option, which is typically used for vendor files, would be to use code-splitting.
https://webpack.js.org/guides/code-splitting/

How to use spriting with Webpack and Sass?

I am moving my build system from Grunt with custom tasks to Webpack. As for JavaScript modules it works great, but I'm not so sure what to do with my Sass stylesheets.
I have dependencies on Sass files in my AMD modules, which Webpack can read and generate bundle.css from. But I would ideally like to have my build pipeline generate sprites using spritesmith, then copy the images to the build dir and use the Sass mixins to generate correct CSS rules.
I have researched this a lot both on SO and Google, but haven't found anyone doing similar scenario. Should I use solely webpack? Or should I maybe have separate Grunt task watching the images, generating sprites and then run Webpack over that?
I have a similar problem, I have a directory full of png files that I need to convert to CSS so that a div with the correct class name will load the image. I would like to use url-loader so that small files are inlined.
The problem is of course that you can't specify a directory as something a loader should load, only existing files.
My solution is to create a custom loader in the png dir and give it itself as input, so it can glob the files in its own dir and export the CSS with all the require statements for the png files.
This is the webpack entry for it:
'!!style!css!./resources/images/images-as-css-loader.coffee!./resources/images/images-as-css-loader'
The loader code (coffeescript but you get the idea):
glob = require 'glob'
path = require 'path'
sizeOf = require 'image-size'
module.exports = (dummy) ->
this.cacheable true
dir = path.dirname this.resourcePath
entries = for file in glob.sync "#{dir}/*.png"
#addDependency file
className = (path.basename file, '.png')
imgDim = sizeOf file
"""
.#{className} {
width: #{imgDim.width}px;
height: #{imgDim.height}px;
background-repeat: no-repeat;
background-image: url('~!!url?limit=1024!#{file}');
}
"""
# Return CSS text
return entries.join ''
You can then use the webpack text extract plugin to move the CSS to a file, which I do for the production build. For dev I just let the style loader inject it.
I had similar problem, the only solution I've been able to come up with was to write my own plugin.

How to optimize a subset of JavaScript files created as RequireJS modules

I have single-page web application that uses RequireJS to organize and structure JavaScript code. Inside the app, I have some JS files that I want to optimize using r.js because they belong to an API that will be consumed by my customers. So, I just want to optimize those files and keep the rest of the code as it is now.
This is my application structure:
app
main.js
many other files and folders
scripts
myAPI
app.js
many other files and folders
require.js
jquery.js
build.js
index.htm
All the JavaScript code is located under the app and scripts folders. As I mentioned before, all those files are defined as RequireJS modules. This is how the main.js looks now:
require.config({
baseUrl: 'scripts',
paths: {
base: 'myAPI/base',
proxy: 'myAPI/proxyObject',
localization: 'myAPI/localization',
app: '../app',
}
});
require(['myAPI/app'],
function (app) {
//app.init....
}
);
As you can see, in the paths configuration I'm defining some aliases that point to myAPI (the folder I want to optimize).
This is how I reference RequireJS from the index.htm file:
<script data-main="app/main" src="scripts/require.js"></script>
This is the build file I created for r.js (scripts/build.js):
({
baseUrl: '.',
out: 'build/myAPI.js',
name: 'myAPI/app',
include: ['some modules'],
excludeShallow: ['some modules defined in the app folder'],
mainConfigFile: '../app/main.js',
optimize: 'uglify2',
optimizeCss: 'none'
})
The optimized file is generated, but I have some challenges trying to use it:
How do I reference that file from the app?
The dependencies to myAPI modules are broken now. RequireJS doesn't find the modules defined in myAPI.
What can I do to keep the aliases defined in require.config.paths working?
Could you please help me with some suggestions or feedback for this situation?
Thanks!!
After doing research, I could solve my problem. I based my solution in this Github project created by James Burke: https://github.com/requirejs/example-libglobal.
First, I had to remove all the dependencies to myAPI individual modules, and create an object that centralizes the access to any internal dependency. Then, I created a r.js script to generate a single file for myAPI. That file is the one that will consumed by the other JS files. That single file can be referenced as a global object or as an AMD module, as James Burke shows in the Github project.
The aliases defined in require.config.paths were no longer necessary.

Categories

Resources