53

So right now I'm working with a prototype where we're using a combination between webpack (for building .tsx files and copying .html files) and webpack-dev-server for development serving. As you can assume we are also using React and ReactDOM as a couple of library dependencies as well. Our current build output is the following structure:

dist -favicon.ico -index.html -main.js -main.js.map // for source-mapping between tsx / js files 

This places ALL of the modules (including library dependencies into on big bundled file). I want the end result to look like this:

dist -favicon.ico -index.html -appName.js -appName.min.js -react.js -react.min.js -reactDOM.js -reactDOM.min.js 

I have references to each of the libraries in index.html and in import statements in the .tsx files. So my question is this... How do I go from webpack producing this gigantic bundled .js file to individual .js files (libraries included, without having to specify each individually)? **Bonus: I know how to do prod/dev environment flags, so how do I just minify those individual files (again without bundling them)?

current webpack.config:

var webpack = require("webpack"); // Assigning node package of webpack dependency to var for later utilization var path = require("path"); // // Assigning node package of path dependency to var for later utilization module.exports = { entry: [ "./wwwroot/app/appName.tsx", // Starting point of linking/compiling Typescript and dependencies, will need to add separate entry points in case of not deving SPA "./wwwroot/index.html", // Starting point of including HTML and dependencies, will need to add separate entry points in case of not deving SPA "./wwwroot/favicon.ico" // Input location for favicon ], output: { path: "./dist/", // Where we want to host files in local file directory structure publicPath: "/", // Where we want files to appear in hosting (eventual resolution to: https://localhost:4444/) filename: "appName.js" // What we want end compiled app JS file to be called }, // Enable sourcemaps for debugging webpack's output. devtool: "source-map", devServer: { contentBase: './dist', // Copy and serve files from dist folder port: 4444, // Host on localhost port 4444 // https: true, // Enable self-signed https/ssl cert debugging colors: true // Enable color-coding for debugging (VS Code does not currently emit colors, so none will be present there) }, resolve: { // Add '.ts' and '.tsx' as resolvable extensions. extensions: [ "", ".ico", ".js", ".ts", ".tsx", ".web.js", ".webpack.js" ] }, module: { loaders: [ // This loader copies the index.html file & favicon.ico to the output directory. { test: /\.(html|ico)$/, loader: 'file?name=[name].[ext]' }, // All files with a '.ts' or '.tsx' extension will be handled by 'ts-loader'. { test: /\.tsx?$/, loaders: ["ts-loader"] } ], preLoaders: [ // All output '.js' files will have any sourcemaps re-processed by 'source-map-loader'. { 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", // "redux": "Redux" // } }; 
6
  • Webpack's sole purpose is to do bundling; are you sure you don't want any bundling, or do you just want some things to bundle and others not to? If it's the latter option, you can see why it'd be required to specify each file individually. Commented Oct 17, 2016 at 22:12
  • 1
    So I like the fact I can do transpiling from Typescript to Javascript with webpack. I know we still need a build system, but don't want to rely solely on gulp or (as what a lot used to use) grunt. I also don't know if using something like npm scripts would provide enough functionality though, unless individual packages out there could serve the same needs. Could you provide any further recommendations given these conditions? Commented Oct 17, 2016 at 22:18
  • 1
    I have already found in the past that webpack allows for chunking, based on common modules... If anyone could provide further information according to the above, that would also resolve my problem. Thanks! Commented Oct 17, 2016 at 23:28
  • 3
    Personally, I think webpack is only a great build tool for bundling, and if you're not wanting bundling, I'd stick with gulp or NPM scripts. Commented Oct 17, 2016 at 23:33
  • 6
    @Jacob Webpack also shines in that it lets you require non-JS files. If you're trying to build an isomorphic app, you have to use webpack on both the client and the server. However, the server really doesn't benefit from bundling. Commented May 9, 2017 at 16:21

3 Answers 3

32

Change the output setting to be name driven e.g.

 entry: { dash: 'app/dash.ts', home: 'app/home.ts', }, output: { path: './public', filename: 'build/[name].js', sourceMapFilename: 'build/[name].js.map' }, 
Sign up to request clarification or add additional context in comments.

2 Comments

Closest to what the eventual solution ended up being after some research. I added a comment of my eventual solution in the explanation above. One downside to using your methodology is that when specifying files of different types as entry points (ie favicon.ico, index.html) for file-loader, they will also be outputted with the .js as well as their original files.
Any idea how much time this saves in a project? If webpack basically did nothing but copy files from input to output, is there much overhead - before adding transpiling and other plugin/loader transforms?
16

To expand upon @basarat's answer, you can use the glob package from node's standard library to build the "entry" config:

const glob = require("glob"); module.exports = [ { target: "node", entry: glob.sync("./src/**/*.test.{ts,tsx}").reduce((acc, file) => { acc[file.replace(/^\.\/src\//, "")] = file; return acc; }, {}), output: { filename: "[name].js", chunkFilename: "[name]-[id].js", path: __dirname + "/dist" }, //... } ]; 

This builds files with the same name as their source, replacing .ts and .tsx with .js.

1 Comment

Actually this helps a lot to get the files and compile as TSC. But then I gets a minify error Uncaught Error: Minified React error #321; visit reactjs.org/docs/error-decoder.html?invariant=321 for the full message or use the non-minified dev environment for full errors and additional helpful warnings.
3

OPs answer copied out of the question

Ended up finding a solution that fit my needs, although, again, in that webpack-y way, requires some additional configuration. Still would like to make it a little more dynamic, but will perfect this at a later point in time. The resolution I was looking for was the ability to "chunk" common modules, but I stated it as filename given "entry"-points provided in webpack. I didn't mind some files being combined, where it made sense, but wanted overall files to be at a component-level given the project wasn't a SPA (single page application).

The additional code ended up being:

plugins: [ new webpack.optimize.CommonsChunkPlugin({ // This plugin is for extracting and created "chunks" (extracted parts of the code that are common and aren't page specific) // One of these instances of plugins needs to be specified for EACH chunk file output desired filename: "common.js", // Filename for this particular set of chunks to be stored name: "common", // Entry point name given for where to pull all of the chunks minChunks: 3 // Minimum number of chunks to be created }) ] 

I also had to parameterize the entry points (see below for example), by variable name so that I could assign react, react-dom, and redux modules to common.js file.

entry: { main: "./wwwroot/app/appName.tsx", // Starting point of linking/compiling Typescript and dependencies, will need to add separate entry points in case of not deving SPA index: "./wwwroot/index.html", // Starting point of including HTML and dependencies, will need to add separate entry points in case of not deving SPA favicon: "./wwwroot/favicon.ico", // Input location for favicon common: [ "react", "react-dom", "redux" ] // All of the "chunks" to extract and place in common file for faster loading of common libraries between pages }, 

1 Comment

Do you have an estimate for how much time NOT bundling saves (in analysis time?) vs bundling?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.