Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extended help section for standard webpack #626

Merged
merged 18 commits into from
Oct 14, 2016

Conversation

bigopon
Copy link
Member

@bigopon bigopon commented Oct 7, 2016

Doc: (setup-webpack.md): Update doc for setup with standard webpack configuration

This gives some basic guide line for standard webpack configuration, enabling flexibility in modifying the configs.

This is a result of as the orginial author refused to make a pull request

@nashwaan
Copy link
Contributor

nashwaan commented Oct 7, 2016

@bigopon That's an excellent documentation. Well done.

You may also want to add in section 8) Reminder another point to:
npm install --save-dev less-loader.

const CopyWebpackPlugin = require('copy-webpack-plugin');
const AureliaWebpackPlugin = require('aurelia-webpack-plugin');
const WebpackMd5Hash = require('webpack-md5-hash');
const DefinePlugin = require('webpack/lib/DefinePlugin');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

require('webpack/lib/DefinePlugin') is redundant. Use new webpack.DefinePlugin( for the same effect.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. Thanks for pointing that out. I also commented out cssnano, but still leave it there just as reminder

Copy link

@boazblake boazblake Oct 7, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bigopon thanks for writing this! I really appreciate the markup.... following your instructions I noticed an error with the commands:

webpack build: 2.1.0.beta-23 should be 2.1.0-beta.23
npm install [email protected] --save-dev should be 2.1.0-beta.0

Also need to:
const DefinePlugin = require('webpack/lib/DefinePlugin');
as webpack wont load with out it

#626

Copy link
Member Author

@bigopon bigopon Oct 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah just realized that, fixed 👍

Also changed webpack version to beta.25

@boazblake did it work for you ? Did you also change new DefinePlugin() to new webpack.DefinePlugin(), this way we don't need to require a module inside webpack

Copy link

@boazblake boazblake Oct 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thats what it was! ...
however, after adding that I now see html-minifier-loader issues:

Module not found: Error: Can't resolve 'html-minifier-loader'
but even
npm install html-minifier html-minifier-loader --save

still resulted in:
ERROR in ./~/html-minifier/~/uglify-js/tools/node.js

Copy link
Member Author

@bigopon bigopon Oct 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah sorry, I fixed that after your comment, shoulda pointed out. I'll check the html-minifier-loader. Don't know why it works for me. Can you try to comment out the line

minifyJS: true

in 'html-minifier-loader' configs and check again ?

Edit: did you install its dependency: html-minifier ? Sorry I missed several things

Copy link

@boazblake boazblake Oct 8, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did as you suggested regarding commenting out minifyJS and still have this error:

ERROR in ./~/html-minifier/~/uglify-js/tools/node.js Module not found: Error: Can't resolve 'fs' in '/Users/Boaz/Desktop/aurelia_webpack_skel/node_modules/html-minifier/node_modules/uglify-js/tools' @ ./~/html-minifier/~/uglify-js/tools/node.js 8:9-22 @ ./~/html-minifier/src/htmlminifier.js @ ./src ^\.\/.*$ @ ./~/aurelia-loader-webpack/dist/commonjs/aurelia-loader-webpack.js @ multi aurelia

I went through the directions and webpack.config line by line so its more than likely I made a mistake or typo... I will copy and paste your code in the morning and let you know.

I really appreciate the help and your hard work!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess that's some loaders loading content asynchronously:

A suggested fix for that is to add:

    node: {
      fs: "empty"
    },

to your base config object.

@boazblake I also updated the first section about dependencies to make it clearer

@nashwaan
Copy link
Contributor

nashwaan commented Oct 8, 2016

May i suggest to use

const metadata = {
    ...
    HMR: process.argv.join('').indexOf('hot') >= 0 || !!process.env.WEBPACK_HMR

and delete the very first line:

const hasProcessFlag = flag => process.argv.join('').indexOf(flag) > -1;

@bigopon
Copy link
Member Author

bigopon commented Oct 8, 2016

@nashwaan Fixed 👍 . I was not sure if any other flags should be used so I extracted it to a separate function after inline-ing it. Originally copied from @easy-webpack

@boazblake I also added a section to guide how to use aurelia plugins. Hope it helps

@boazblake
Copy link

@nashwaan @bigopon

Thank you for your help!

So far I am still getting the same 'fs' error... even with copy and paste... so it must be something else I have done - If it works for the two of you I would image its all good though.
Ill take a look at the guides for the plugins and make sure I am doing it correctly - Iv only been coding since March of this year so I am more than likely making more than a couple of errors.

@nashwaan
Copy link
Contributor

nashwaan commented Oct 8, 2016

@bigopon
In Section 9, point 3:
3. Start your project to check if the plugin is propery config. => properly configured.

Apart from this typo, point 3 provides a workaround if the aurelia plugin itself has improper package.json configuration. While the information you provided is very valuable, I find it inconvenient to put that in the official aurelia documentation and ask the user to put the fix in their package.json. I think it will be more convenient if you inform the maintainers of the aurelia plugins to properly configure their package.json, unless these plugins are not the official aurelia plugins. In this case, I wonder if this information is available for the plugin authors.

@bigopon
Copy link
Member Author

bigopon commented Oct 8, 2016

Typo fixed.

I don't think it's the best idea to put in official document about plugins, but future plugin may have that problem and i think it's quite necessary to let other developers know. What do you suggest @nashwaan ?

@nashwaan
Copy link
Contributor

nashwaan commented Oct 9, 2016

Ideally, the user should not be bothered about properly configuring aurelia.build.resources in his package.json in case the package.json of the plugin is not doing that right. This is very inconvenient and many users are likely to miss/forget about this workaround. It would be great if you can do pull requests in the package.json for the plugins that you are aware of that are having this issue. The idea is to avoid shifting the burden to the user side as much as possible.

Probably, the source of the problem is we don't have A Plugin Author section in the docs as mentioned here. I guess that's why such a problem exists in the first place and quite possibly will grow more. Until a doc for developing a plugin is provided, then I think it is ok to keep the information you mentioned in section 9.3 as a workaround solution.

@nashwaan
Copy link
Contributor

nashwaan commented Oct 9, 2016

@bigopon
Looking at webpack.config.js file, I find it intimidating for new users. Yes, you did a great job to make the file achieve the best for a professional aurelia project. But I would suggest to provide a simpler version (minimal) that helps to get aurelia properly running for a new project. After this simple version, you can put the professional version either as a whole or as a diff. What do you think?

@nashwaan
Copy link
Contributor

nashwaan commented Oct 9, 2016

@bigopon In webpack 2, It is no longer necessary to manually eat up the string after the extension in test. For example, (\?\S*)? portion in the following line:

                test: /\.(png|jpe?g|gif|svg|eot|woff|woff2|ttf)(\?\S*)?$/,

Can be safely removed:

                test: /\.(png|jpe?g|gif|svg|eot|woff|woff2|ttf)$/,

@nashwaan
Copy link
Contributor

nashwaan commented Oct 9, 2016

@bigopon , you mentioned in the NOTE of this page:

During development, loading page will have splash message appear without style for a short period but it should be fine for production build as all style will be extracted to a css file and loaded before any content.

Another solution will be (from Webpack from First Principles see at 13:10) to ensure the css, which transformed into javascript, is loaded in the <head> tag rather than the <body> which is the behavior of HtmlWebpackPlugin by default.
I.e:

        new HtmlWebpackPlugin({
            inject: 'head', // to ensure css styles are inserted into <head> before processing <body>
            title: title,
            template: 'index.html',
            chunksSortMode: 'dependency'
        }),

And if this solves the problem, will this make extract-text-webpack-plugin unnecessary?

@boazblake
Copy link

@nashwaan @bigopon
I went back over my steps and it appears that even though I had npm install after pasting in the dependencies, nothing had actually happened and all I had needed to do was explicitly install html-webpack-plugin.
Good job with the guide!

@bigopon
Copy link
Member Author

bigopon commented Oct 9, 2016

@boazblake glad that it worked for you

@nashwaan I separated the guide into basic and advanced sections. It does look simpler to start with and more beginner friendly. All of your suggestions have been added. For loading style in a style.min.css, I think it's better to have css loaded in a separate file than together with javascript.

@boazblake
Copy link

@bigopon @nashwaan

Would you happen to know why the app no longer 'sees' the location of my svgs and jpegs?
Many thanks to you guys!

@nashwaan
Copy link
Contributor

Looking at the basic version. Hmmm, I was thinking of even simpler version. A minimal version with no gadgets, no debug, no optimizations, and not much comment.

More preciesly:

const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const AureliaWebpackPlugin = require('aurelia-webpack-plugin'); 
const project = require('./package.json');

module.exports = {
    entry: {
        app: [], // <-- this array will be filled by the aurelia-webpack-plugin
        aurelia: Object.keys(project.dependencies).filter(dep => dep.startsWith('aurelia-'))
    },
    output: {
        path: path.resolve('dist'),
        filename: '[name].bundle.js',
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                exclude: /node_modules/, // or include: path.resolve('src'),
                loader: 'babel-loader',
                query: {
                    presets: ['es2015', 'stage-1'],
                    plugins: ['transform-decorators-legacy']
                }
            },
            {
                test: /\.html$/,
                exclude: /index\.html$/, // index.html will be taken care by HtmlWebpackPlugin
                loader: 'html-loader'
            },
            {
                test: /\.css$/, 
                loaders: ['style-loader', 'css-loader']
            },
            {
                test: /\.(png|jpe?g|gif|svg|eot|woff|woff2|ttf)$/,
                loader: 'url-loader'
            }
        ]
    },
    plugins: [
        new webpack.ProvidePlugin({
            regeneratorRuntime: 'regenerator-runtime', // to support await/async syntax
            Promise: 'bluebird', // because Edge browser has slow native Promise object
            jQuery: 'jquery', // because 'bootstrap' by Twitter depends on jQuery
        }),
        new AureliaWebpackPlugin({
            root: path.resolve(),
            src: path.resolve('src'),
            baseUrl: '/'
        }),
        new HtmlWebpackPlugin({
            template: 'index.html',
        }),
        new webpack.optimize.CommonsChunkPlugin({ // to eliminate code duplication across bundles
            name: ['aurelia']
        })
    ]
};

Even preferably without HtmlWebpackPlugin but could not figure out how to do this.

The aim is to make it more digestible for newcomers so they would understand what is minimally required to get aurelia running. More of a hello world webpack config for aurelia.

I would also prefer to remove ejs syntax from index.html

<!DOCTYPE html>
<html>
  <head>
    <title>Aurelia Webpack Skeleton</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <base href="/">
    <!-- imported CSS are concatenated and added automatically -->
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="format-detection" content="telephone=no">
  </head>
  <body aurelia-app="main">
    <div class="splash">
      <div class="message">Aurelia Webpack Skeleton</div>
      <i class="fa fa-spinner fa-spin"></i>
    </div>
    <!-- Uncomment below line for Webpack Dev Server auto reload -->
    <!--<script src="/webpack-dev-server.js"></script>-->
  </body>
</html>

Again, the idea is to throw less technologies in the beginning.

@lares83
Copy link

lares83 commented Oct 10, 2016

Hi,
I tried your guildlines and after that I got this error

ERROR in Template execution failed: ReferenceError: development is not defined

ERROR in   ReferenceError: development is not defined

After some investigation I found bug in your code namely in

new webpack.DefinePlugin({
              '__DEV__': true,
              'ENV': metadata.ENV,
              'HMR': metadata.HMR,
              'process.env': {
                  'ENV': metadata.ENV,
                  'NODE_ENV': metadata.ENV,
                  'HMR': metadata.HMR,
                  'WEBPACK_HOST': metadata.host,
                  'WEBPACK_PORT': metadata.port
              }
          })

there should be stringified ENV and WEBPACK values so it should be sth like this:

new webpack.DefinePlugin({
            '__DEV__': true,
            'ENV': JSON.stringify(metadata.ENV),
            'HMR': metadata.HMR,
            'process.env': {
                'ENV': JSON.stringify(metadata.ENV),
                'NODE_ENV': JSON.stringify(metadata.ENV),
                'HMR': metadata.HMR,
                'WEBPACK_HOST': JSON.stringify(metadata.host),
                'WEBPACK_PORT': JSON.stringify(metadata.port)
            }
        })

After that everything works fine

@bigopon
Copy link
Member Author

bigopon commented Oct 10, 2016

@nashwaan I'm not sure if merging Aurelia & bootstrap chunks would be ok. All of official docs seem to separate them.

@lares83 Haven't tried to run after removing JSON.stringify 😄

@boazblake I think something wrong with your configurations. Btw what do you mean by not see?

@bigopon
Copy link
Member Author

bigopon commented Oct 11, 2016

@niieani @nashwaan

Some typos fixed, I also added suggested production setup section

Copy link
Contributor

@niieani niieani left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one more typo :) then we can merge


3. **Javascript optimization**.

* To diliver a smaller bundle for production. Add to your `plugins` in the configuration:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

diliver -> deliver

@lares83
Copy link

lares83 commented Oct 11, 2016

@boazblake no problem :)
@bigopon @niieani there is one more bug namely when I launch
npm run build:prod
I'm receiving this error

Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
 - configuration.entry['app'] should be one of these:
   string | [string]
   The entry point for one output file.
 - configuration.entry should be one of these:
   object { <key>: string | [string] } | string | [string]
   The entry point(s) of the compilation.

it looks like in webpack.beta25 there can't be an empty array in an entry

entry: {
        app: [], // <-- this array will be filled by the aurelia-webpack-plugin
        aurelia: Object.keys(project.dependencies).filter(dep => dep.startsWith('aurelia-'))
    },

@niieani
Copy link
Contributor

niieani commented Oct 11, 2016

@lares83 I've opened an issue webpack/webpack#3123

@lares83
Copy link

lares83 commented Oct 11, 2016

@niieani great thanks :)

@nashwaan
Copy link
Contributor

@niieani In the initial webpack.config.js, there are two entry junks for aurelia:

const aureliaBootstrap = [
    'aurelia-bootstrapper-webpack',
    'aurelia-polyfills',
    'aurelia-pal-browser',
    'regenerator-runtime'
];
const aureliaModules = Object.keys(project.dependencies).filter(dep => dep.startsWith('aurelia-'));
module.exports = {
    entry: {
        'app': [],
        'aurelia-bootstrap': aureliaBootstrap,
        'aurelia': aureliaModules.filter(pkg => aureliaBootstrap.indexOf(pkg) === -1)
    },

In the simplified version, we used this only:

module.exports = {
    entry: {
        'app': [],
        'aurelia': Object.keys(project.dependencies).filter(dep => dep.startsWith('aurelia-'))
    },

But, for a production setup, does the first version provide faster initial loading of aurelia? Aren't aurelia-bootstrap chunk and aurelia chunk injected in the index.html at the same time?

@niieani
Copy link
Contributor

niieani commented Oct 12, 2016

@bigopon @nashwaan using project.dependencies is incomplete though, because those dependencies have their dependencies too, so some Aurelia packages may end up in the app chunk if imported from there too.

Separating aurelia-bootstrap and aurelia entrypoints was necessary before the most recent changes to the way bootstrapper-webpack works, because of the way PAL was initialized. Right now it should work without the additional chunk, but I've not tested it. They're injected into index.html at the same time, but they're loaded synchronously, which means bootstrapper packages gets loaded first.

@EisenbergEffect
Copy link
Contributor

Wow. Tons of collaboration going on here. Great work all! Where are we on this? Ready to go or needs more iterations?

@nashwaan
Copy link
Contributor

nashwaan commented Oct 13, 2016

@EisenbergEffect Generally, I guess the doc is ready. Thanks for the excellent efforts by @bigopon.

The only one point that I am still not sure about is the comment by @niieani

using project.dependencies is incomplete though...

I assume @niieani suggested to revert back to manual loading of aurelia modules:

const coreBundles = {
  bootstrap: [
    'aurelia-bootstrapper-webpack',
    'aurelia-polyfills',
    'aurelia-pal',
    'aurelia-pal-browser',
    'regenerator-runtime',
    'bluebird'
  ],
  aurelia: [
    'aurelia-bootstrapper-webpack',
    'aurelia-binding',
    'aurelia-dependency-injection',
    'aurelia-event-aggregator',
    'aurelia-framework',
    'aurelia-history',
    'aurelia-history-browser',
    'aurelia-loader',
    'aurelia-loader-webpack',
    'aurelia-logging',
    'aurelia-logging-console',
    'aurelia-metadata',
    'aurelia-pal',
    'aurelia-pal-browser',
    'aurelia-path',
    'aurelia-polyfills',
    'aurelia-route-recognizer',
    'aurelia-router',
    'aurelia-task-queue',
    'aurelia-templating',
    'aurelia-templating-binding',
    'aurelia-templating-router',
    'aurelia-templating-resources'
  ]
}

rather than using project.dependencies as shown in my previous comment. If manual loading is more accurate, then lets use it in the final webpack.config.js file.

@nashwaan
Copy link
Contributor

@EisenbergEffect Also, it seems that there is an issue as reported by @lares83 regarding empty array [] in the entry chunks. This is an issue in the latest beta version of webpack 2 (webpack.beta25) and @niieani has reported it webpack/webpack#3123. Now it is pending with the maintainer of webpack project.

@niieani
Copy link
Contributor

niieani commented Oct 13, 2016

@nashwaan that's right. We should revert back to manually listing all Aurelia modules to be included in the aurelia bundle. We probably don't need the bootstrap entrypoint though. A workaround for the webpack issue could be using ['./src/main'] instead of [] which should be added to app in any case.

@nashwaan
Copy link
Contributor

@bigopon As advised by @niieani , I suggest to do following changes in the final webpack.config.js:

const aureliaModules: [
    'aurelia-bootstrapper-webpack',
    'aurelia-binding',
    'aurelia-dependency-injection',
    'aurelia-event-aggregator',
    'aurelia-framework',
    'aurelia-history',
    'aurelia-history-browser',
    'aurelia-loader',
    'aurelia-loader-webpack',
    'aurelia-logging',
    'aurelia-logging-console',
    'aurelia-metadata',
    'aurelia-pal',
    'aurelia-pal-browser',
    'aurelia-path',
    'aurelia-polyfills',
    'aurelia-route-recognizer',
    'aurelia-router',
    'aurelia-task-queue',
    'aurelia-templating',
    'aurelia-templating-binding',
    'aurelia-templating-router',
    'aurelia-templating-resources'
];

module.exports = {
    entry: {
        'app': ['./src/main'],
        'aurelia': aureliaModules
    },

Note: not tested.

@bigopon
Copy link
Member Author

bigopon commented Oct 13, 2016

@nashwaan @niieani @EisenbergEffect
This all credit goes to @nashwaan with his original issue. I believe this will help reduce a lot of issue related to the webpack skeleton for awhile before cli officially supports webpack

Fixed for last suggestion. I could go further with Javascript mangling section in last section, by adding a list of private properties in aurelia core modules to help reduce bundle size a lot more, but wasn't sure if it should be.

@lares83
Copy link

lares83 commented Oct 13, 2016

@bigopon I found a small mistake in docs (Suggested Production Setup) there should be
const aureliaModules = [ instead of const aureliaModules: [

I think that we should also add aureliaModules in "Basic configuration" section

@bigopon bigopon closed this Oct 13, 2016
@bigopon bigopon reopened this Oct 13, 2016
@bigopon
Copy link
Member Author

bigopon commented Oct 13, 2016

Accdidentally hit close & comment

@lares83 I think for very basic version, having aurelia core bundle's dependencies into aurelia is ok. @nashwaan has a good point here is that keep this section extremely simple so anyone can start without feeling intimidated. We have a last section for production build, with things done right so probably it won't be a problem.

Maybe leave the decision to @EisenbergEffect

@lares83
Copy link

lares83 commented Oct 13, 2016

@bigopon I see your point, thanks for explanation :)

I wondering about one more thing, do we still need bluebird?
As far as I know slow promises in Edge have already been fixed in Edge 14
(https://wpdev.uservoice.com/forums/257854-microsoft-edge-developer/suggestions/11329845-improve-promise-implementation-performance?tracking_code=a6dbd08f77bf7c9b26693bac96309a81)

@EisenbergEffect @niieani what do you think about it?

Copy link
Contributor

@niieani niieani left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm @niieani, and I approve this PR.

Thanks for all the hard work @bigopon and for the help/ideas/comments, @lares83 and @nashwaan.

Seal of approval

CC: @EisenbergEffect

@EisenbergEffect EisenbergEffect merged commit 9615f64 into aurelia:master Oct 14, 2016
@lares83
Copy link

lares83 commented Oct 14, 2016

@niieani I'm still testing this webpack configuration and I stubmle across one issue namely when I setup in package.json

"aurelia": {
    "build": {
      "resources": [
        {
            "path": "users",
            "bundle": "users",
            "lazy": true
        }
      ]
    }
  },

and launch npm run prod:build I should receive sth like this

0.fe2de0b647382fef77d8.chunk.js    2.07 kB       0  [emitted]  users
app.9c05dcbfe6ae9cb85b5f.bundle.js     32.9 kB       1  [emitted]  app
aurelia.6a3f85872c3812bc64f5.bundle.js     460kB       2  [emitted]  aurelia

but I get only

app.e80a0814f88eb6feb289.bundle.js  32.9 kB       0  [emitted]  app
aurelia.4c55aae59e21d975bf8b.bundle.js   460 kB    1  [emitted]  aurelia

and additionally these warnings

WARNING in ./src ^\.\/.*$
Module not found: Error: Can't resolve 'bundle' in 'G:\aurelia\skeleton\src'
 @ ./src ^\.\/.*$
 @ ./~/aurelia-loader-webpack/dist/native-modules/aurelia-loader-webpack.js
 @ multi aurelia

WARNING in ./src ^\.\/.*$
Module not found: Error: Can't resolve 'bundle' in 'G:\aurelia\skeleton\src'
 @ ./src ^\.\/.*$
 @ ./~/aurelia-loader-webpack/dist/native-modules/aurelia-loader-webpack.js
 @ multi aurelia

@niieani
Copy link
Contributor

niieani commented Oct 15, 2016

@lares83 is there an issue for the problem you're describing?

@lares83
Copy link

lares83 commented Oct 15, 2016

@niieani I haven't seen any issue reported for this problem.
It works fine with a current version of skeleton-esnext-webpack (webpack 2.1.0-beta.22), so it could be another problem with webpack 2.1.0-beta.25

@peterver
Copy link

I have no clue where to report this, sorry if this is not the correct place :3

After switching from the @easy-webpack config to the regular one i started getting issues with the presets for babel (namely : stage-1 and es2015 not being found),

In case anyone else was having this issue, replacing babel-env with babel-preset-stage-1 and babel-preset-es2015 does the trick.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants