Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Webpack dev server : define WWW root

Using webpack I have separated source files from distribution files.

One problem that I have run into relates to output.publicPath, if I define one, the generated index.html has the wrong path to CSS and JS resources. I think the problem is related to extract-text-webpack-plugin See: https://github.com/webpack-contrib/extract-text-webpack-plugin/issues/246

Now that I have separated the code into source and distribution my index.html is available at http://localhost/target/classes/war. And every page refresh needs to have the URL typed in by hand because the routes fail to recognise the folder name. The <base /> tag in the head does not seem to have an effect.

How can I instruct webpack to display the contents of the folder ./target/classes/war at http://localhost/ ? (without using output.publicPath)

For completeness, find below the entire webpack.config.js as it stands :

var path = require('path');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');
var GoogleFontsPlugin = require("google-fonts-webpack-plugin");

module.exports = {

    entry: {
        polyfills: './src/main/webapp/polyfills.ts',
        vendor: './src/main/webapp/vendor.ts',
        app: './src/main/webapp/app/core/global/main/main.ts'
    },

    output: {
        filename: 'target/classes/war/script/[name].[hash].bundle.js'
    },

    resolve: {
        extensions: ['.ts', '.js'],

        alias: {
            css: path.resolve(__dirname, "src/main/webapp/WEB-INF/scss"),
            src: path.resolve(__dirname, "src/main/webapp"),
            dist: path.resolve(__dirname, "target/class/war")
        }
    },

    module: {

        rules: [
            {
                test: /\.ts$/,
                loaders: [
                    {
                        loader: 'awesome-typescript-loader',
                        options: {
                            configFileName: path.resolve(__dirname, "src/main/webapp/WEB-INF/conf/tsconfig.json")
                        }
                    },
                    'angular2-template-loader'
                ]
            },
            {
                test: /\.html$/,
                loader: 'html-loader'
            },
            {
                test: /\.(png|jpe?g|gif|svg|woff|woff2|ttf|eot|ico)$/,
                loaders: [
                    {
                        loader: "file-loader",
                        options: {
                            hash: "sha512",
                            digest: "hex",
                            name: "/target/classes/war/assets/[name].[hash].[ext]"
                        }
                    }
                ]
            },
            {
                test: /\.(css|scss)$/,
                exclude: path.resolve(__dirname, "src/main/webapp/scss"),
                include: path.resolve(__dirname, "src/main/webapp/app"),
                loaders: [
                    {
                        loader: "raw-loader"
                    },
                    {
                        loader: "sass-loader"
                    }
                ]

            },
            {
                test: /\.(css|scss)$/,
                exclude: path.resolve(__dirname, "src/main/webapp/app"),
                use: [
                    {
                        loader: "style-loader" // creates style nodes from JS strings
                    }, 
                    {
                        loader: "css-loader" // translates CSS into CommonJS
                    },
                    {
                        loader: "resolve-url-loader" // compiles Sass to CSS
                    },
                    {
                        loader: "sass-loader" // compiles Sass to CSS
                    }
                ]
            }
        ]
    },
    plugins: [
        // Workaround for angular/angular#11580
        new webpack.ContextReplacementPlugin(
                // The (\\|\/) piece accounts for path separators in *nix and Windows
                /angular(\\|\/)core(\\|\/)@angular/,
                path.resolve(__dirname, "src/main/webapp"), // location of your src
                {} // a map of your routes
        ),

        new webpack.optimize.CommonsChunkPlugin({
            name: ['app', 'vendor', 'polyfills']
        }),

        new HtmlWebpackPlugin({
            template: 'src/main/webapp/index.html',
            filename: 'target/classes/war/index.html',
            chunksSortMode: function (chunk1, chunk2) {
                var order = ['polyfills', 'vendor', 'app'];
                var order1 = order.indexOf(chunk1.names[0]);
                var order2 = order.indexOf(chunk2.names[0]);
                return order1 - order2;
            }
        }),

        new ExtractTextPlugin({
            filename: "target/classes/war/css/styles.[contenthash].css"
        }),
        new GoogleFontsPlugin({
            fonts: [
                {family: "Lato"}
            ],
            path: "src/main/webapp/scss/fonts/",
            filename: "src/main/webapp/scss/fonts/fonts.css"
        })
    ]
};
like image 551
klonq Avatar asked Jun 18 '17 16:06

klonq


2 Answers

Result of this webpack config is.

<script type="text/javascript" src="http://localhost/target/classes/war/script/app.5e643bae101bd4743814.bundle.js"></script>

Config

var path = require('path');
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
var ExtractTextPlugin = require('extract-text-webpack-plugin');

module.exports = {
 entry: {
  // it's .js now for testing
  app: './src/main/webapp/app/core/global/main/main.js'
 },    
 output: {
  filename: 'target/classes/war/script/[name].[hash].bundle.js',
  publicPath: 'http://localhost/'
 },
 module: {
  rules: [
   {
    test: /\.(css|scss)$/,
    loaders: [
     {
      loader: "raw-loader"
     },
     {
      loader: "sass-loader"
     }
    ]
   },
  ]
 },
 plugins: [

  new HtmlWebpackPlugin({
   // it's .ejs now
   template: 'src/main/webapp/index.template.ejs',
   filename: 'target/classes/war/index.html',
  }),

  new ExtractTextPlugin({
   filename: "target/classes/war/css/styles.[contenthash].css"
  }),    
 ]
};
like image 175
Yoruba Avatar answered Nov 19 '22 20:11

Yoruba


If I get your issue right, you want to use target/classes/war as a target path for your application's build artefacts.

You are probably using the wrong output property: instead of output.publicPath, just use output.path.

output: {
    filename: 'script/[name].[hash].bundle.js',
    path: path.resolve(__dirname, 'target/classes/war'),
},

output.publicPath is usually the right option if you need to integrate your build with a CDN.

Note that you should also remove HtmlWebpackPlugin's layout setting.

like image 1
Andrea Carraro Avatar answered Nov 19 '22 19:11

Andrea Carraro