Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Webpack 2 - How to stop generating .js files for CSS and HTML?

I'm a total newcomer to Webpack (2) so please forgive me for my simple understanding so far.

Following from a few tutorials around the web, I've cobbled together a working package.json and webpack.babel.config.js file.

Essentially, I am trying to turn SCSS into CSS, Pug into HTML and JS into Babel'd JS.

When I run my dist command, it produces the files, but also along with it, are .js files for each .scss and .html etc. Hopefully the image below can illustrate this:

enter image description here

Ideally what I'm after is simply, app.css, index.html and app.js.

webpack.babel.config.js

import webpack from 'webpack';
import path from 'path';
import autoprefixer from 'autoprefixer';
import ExtractTextPlugin from 'extract-text-webpack-plugin';
import HtmlWebpackPlugin from 'html-webpack-plugin';

const extractHtml = new ExtractTextPlugin({
  filename: '[name].html'
});

const extractPug = new ExtractTextPlugin({
  filename: '[name].[contenthash].pug'
});

const extractScss = new ExtractTextPlugin({
  filename: '[name].[contenthash].css',
  allChunks: true
});

let config = {
  stats: {
    assets: false,
    colors: true,
    version: false,
    hash: true,
    timings: true,
    chunks: false,
    chunkModules: false
  },
  entry: {
    'dist/html/app': [
      path.resolve(__dirname, 'src/pug/app.pug')
    ],
    'dist/js/app': [
      path.resolve(__dirname, 'src/js/app.js')
    ],
    'dist/css/app': [
      path.resolve(__dirname, 'src/scss/app.scss')
    ]
  },
  output: {
    path: path.resolve(__dirname, './'),
    filename: '[name].js'
  },
  module: {
    rules: [
      {
        test: /\.pug$/,
        use: extractHtml.extract({
          use: ['html-loader','pug-html-loader?pretty=false&exports=false']
        })
      },
      {
        test: /\.js$/,
        exclude: /(node_modules|bower_components)/,
        use: ['babel-loader']
      },
      {
        test: /\.scss$/,
        use: extractScss.extract({
          use: ['css-loader', 'postcss-loader', 'sass-loader']
        })
      }
    ]
  },
  devServer: {
    contentBase: path.join(__dirname, 'dist'),
    compress: false,
    stats: 'errors-only',
    open: false
  },
  plugins: [
    new HtmlWebpackPlugin({
      title: 'Portfolio',
      // minify: {
      //   collapseWhitespace: true
      // },
      hash: true,
      template: './dist/html/app.html',
      filename: 'index.html'
    }),
    new webpack.LoaderOptionsPlugin({
      minimize: false,
      debug: true,
      options: {
        babelLoader: {
          presets: [
            ['es2015']
          ]
        },
        postcss: [
          autoprefixer({
            browsers: ['last 2 versions', 'Explorer >= 9', 'Android >= 4']
          })
        ],
        sassLoader: {
          includePaths: [
            path.resolve(__dirname, 'node_modules/sanitize.css/')
          ]
        }
      }
    }),
    extractScss,
    extractHtml,
    extractPug
  ]
}

export default config;

package.json

{
  "name": "portfolio",
  "version": "1.0.0",
  "description": "Portfolio of Michael Pumo",
  "main": "index.js",
  "scripts": {
    "dev": "webpack-dev-server",
    "prod": "webpack -p",
    "dist": "webpack --config webpack.config.babel.js"
  },
  "author": "Michael Pumo",
  "license": "ISC",
  "devDependencies": {
    "autoprefixer": "^6.7.7",
    "babel-core": "^6.24.0",
    "babel-loader": "^6.4.1",
    "babel-preset-es2015": "^6.24.0",
    "css-loader": "^0.27.3",
    "extract-text-webpack-plugin": "^2.1.0",
    "html-loader": "^0.4.5",
    "html-webpack-plugin": "^2.28.0",
    "html-webpack-pug-plugin": "^0.0.3",
    "node-sass": "^4.5.0",
    "postcss-loader": "^1.3.3",
    "pug": "^2.0.0-beta11",
    "pug-html-loader": "1.1.1",
    "sass-loader": "^6.0.3",
    "style-loader": "^0.14.1",
    "webpack": "^2.2.1",
    "webpack-dev-server": "^2.4.2"
  }
}

I have many other issues I'd like to resolve too but I'm taking it one issue at a time. Thanks for your help.

like image 629
Michael Giovanni Pumo Avatar asked Mar 17 '17 15:03

Michael Giovanni Pumo


1 Answers

You don't want to use multiple entries, but instead add it to a single entry. For it to work nicely with the extract-text-webpack-plugin you should also change the output a little. It makes it much easier when you set output.path to the dist/ directory, which also makes more sense conceptually. You'll have one entry point for app and then you set the output for the different file types to the corresponding directories. For JavaScript that's the output.filename option, which you want in js/. Your entry and output should look likes this:

entry: {
  app: [
    path.resolve(__dirname, 'src/pug/app.pug'),
    path.resolve(__dirname, 'src/js/app.js'),
    path.resolve(__dirname, 'src/scss/app.scss')
  ]
},
output: {
  path: path.resolve(__dirname, 'dist'),
  filename: 'js/[name].js'
},

And you do the same thing as with output.filename for the filename in the extract text plugins:

const extractHtml = new ExtractTextPlugin({
  filename: 'html/[name].html'
});

const extractScss = new ExtractTextPlugin({
  filename: 'css/[name].[contenthash].css',
  allChunks: true
});

You didn't use extractPug at all, so I left it off and you probably want to remove it.

The output will look likes this:

dist
├─ css
│  └─ app.50352154102b272d39e16c28ef00c1ac.css
├─ html
│  └─ app.html
├─ js
│  └─ app.js
└─ index.html

Now you also have index.html in the dist directory and you can simply deploy the dist directory, as it's self-contained.

On a side note: You should not use ./dist/html/app.html as a template to html-webpack-plugin but instead use the .pug file directly with the pug-loader, which means that you don't even need to add it to the entry or extract the HTML.

like image 69
Michael Jungo Avatar answered Oct 17 '22 15:10

Michael Jungo