web-dev-qa-db-fra.com

Demandez à Webpack de ne pas regrouper les fichiers

Donc, en ce moment, je travaille avec un prototype où nous utilisons une combinaison entre webpack (pour créer des fichiers .tsx et copier des fichiers .html) et webpack-dev-server pour le développement. Comme vous pouvez le supposer, nous utilisons également React et ReactDOM comme deux dépendances de bibliothèque également. Notre sortie de construction actuelle est la structure suivante:

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

Cela place TOUS les modules (y compris les dépendances de bibliothèque dans un gros fichier groupé). Je veux que le résultat final ressemble à ceci:

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

J'ai des références à chacune des bibliothèques dans index.html et dans les instructions d'importation dans les fichiers .tsx. Alors ma question est la suivante ... Comment passer du webpack produisant ce gigantesque fichier .js groupé à des fichiers .js individuels (bibliothèques incluses, sans avoir à les spécifier individuellement)? ** Bonus: je sais comment faire des drapeaux d'environnement prod/dev, alors comment puis-je simplement réduire ces fichiers individuels (encore une fois sans les regrouper)?

webpack.config actuel:

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"
    // }
};

Mise à jour: J'ai fini par trouver une solution qui répondait à mes besoins, même si, encore une fois, de cette manière webpack-y, nécessite une configuration supplémentaire. J'aimerais toujours le rendre un peu plus dynamique, mais je le perfectionnerai plus tard. La résolution que je cherchais était la possibilité de "fragmenter" des modules communs, mais je l'ai indiqué comme nom de fichier en fonction des points "d'entrée" fournis dans le webpack. Cela ne me dérangeait pas que certains fichiers soient combinés, là où cela avait du sens, mais je voulais que les fichiers globaux soient au niveau des composants étant donné que le projet n'était pas un SPA (application d'une seule page).

Le code supplémentaire a fini par être:

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
    })
]

J'ai également dû paramétrer les points d'entrée (voir ci-dessous par exemple), par nom de variable afin de pouvoir affecter les modules react, react-dom et redux au fichier common.js.

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
},
24
B. Blunt

Modifiez le paramètre output pour qu'il soit piloté par le nom par exemple.

    entry: {
        dash: 'app/dash.ts',
        home: 'app/home.ts',
    },
    output: {
        path: './public',
        filename: 'build/[name].js',
        sourceMapFilename: 'build/[name].js.map'
    },
14
basarat

Pour développer la réponse de @ basarat, vous pouvez utiliser le package glob de la bibliothèque standard de node pour construire la configuration "entry":

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"
    },
    //...
  }
];

Cela crée des fichiers avec le même nom que leur source, en remplaçant .ts et .tsx avec .js.

3
Mike Marcacci