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

webpack v4 compatibility upgrade #12

Merged

Conversation

thescientist13
Copy link
Collaborator

@thescientist13 thescientist13 commented Mar 12, 2018

Related Issue

resolves #9 , to upgrade the project to support webpack v4

Summary

Started the process of upgrading to webpack v4. Got a couple expected errors from HtmlWebpackPlugin and ExtractTextWebpackPlugin each after upgrading webpack but was able to resolve those easily by upgrading them as well.

Changes

  1. Updated to webpack@^4.0.0 (4.8.2) and installed webpack-cli, which is needed to run webpack from the command line now
  2. Migrated from compiler.plugins API to compiler.hooks API (only "main" change)
  3. Migrated to MiniCssExtractPlugin (deprecated usage of ExtractTextWebpackPlugin)
  4. Updated to latest version of HtmlWebpackPlugin
  5. Updated specs / asserts accordingly based on newer observed behavior I saw (which I am taking for face value, but please feel free to suggest a different approach).
  6. Set node engine in package.json to `>=6.0.0"
  7. Updated README

TODO

  1. resolve conflicts
  2. Upgrade to MiniCssExtracttPlugin
  3. Set node engine in package.json

Misc

Note: This since been resolved since this PR was through a correction in a CSS comment in index.css. webpack wasn't outputting build files as a result, hence the ENOENT error👇

  HtmlCriticalWebpackPlugin Cases: Generate Critical CSS
    minimum configuration
      Unhandled rejection Error: ENOENT: no such file or directory, open '/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/test/cases/generate-critical-css/build/index.html'
    at Object.fs.openSync (fs.js:646:18)
    at Object.fs.readFileSync (fs.js:551:33)
    at webpack (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/test/cases/generate-critical-css/generate-critical-css.spec.js:17:36)
    at hooks.done.callAsync.err (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/webpack/lib/Compiler.js:152:13)
    at AsyncSeriesHook.eval [as callAsync] (eval at create (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/tapable/lib/HookCodeFactory.js:24:12), <anonymous>:6:1)
    at AsyncSeriesHook.lazyCompileHook [as _callAsync] (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/tapable/lib/Hook.js:35:21)
    at onCompiled (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/webpack/lib/Compiler.js:150:21)
    at hooks.afterCompile.callAsync.err (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/webpack/lib/Compiler.js:470:14)
    at AsyncSeriesHook.eval [as callAsync] (eval at create (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/tapable/lib/HookCodeFactory.js:24:12), <anonymous>:6:1)
    at AsyncSeriesHook.lazyCompileHook [as _callAsync] (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/tapable/lib/Hook.js:35:21)
    at compilation.seal.err (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/webpack/lib/Compiler.js:467:30)
    at AsyncSeriesHook.eval [as callAsync] (eval at create (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/tapable/lib/HookCodeFactory.js:24:12), <anonymous>:6:1)
    at AsyncSeriesHook.lazyCompileHook [as _callAsync] (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/tapable/lib/Hook.js:35:21)
    at hooks.optimizeAssets.callAsync.err (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/webpack/lib/Compilation.js:957:35)
    at AsyncSeriesHook.eval [as callAsync] (eval at create (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/tapable/lib/HookCodeFactory.js:24:12), <anonymous>:6:1)
    at AsyncSeriesHook.lazyCompileHook [as _callAsync] (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/tapable/lib/Hook.js:35:21)
    at hooks.optimizeChunkAssets.callAsync.err (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/webpack/lib/Compilation.js:948:32)
    at _err0 (eval at create (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/tapable/lib/HookCodeFactory.js:24:12), <anonymous>:11:1)
    at /Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/uglifyjs-webpack-plugin/dist/index.js:266:11
    at step (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/uglifyjs-webpack-plugin/dist/uglify/index.js:90:11)
    at done (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/uglifyjs-webpack-plugin/dist/uglify/index.js:99:22)
    at tryCatcher (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/bluebird/js/release/util.js:16:23)
    at Promise._settlePromiseFromHandler (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/bluebird/js/release/promise.js:512:31)
    at Promise._settlePromise (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/bluebird/js/release/promise.js:569:18)
    at Promise._settlePromise0 (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/bluebird/js/release/promise.js:614:10)
    at Promise._settlePromises (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/bluebird/js/release/promise.js:693:18)
    at Promise._fulfill (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/bluebird/js/release/promise.js:638:18)
    at Promise._resolveCallback (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/bluebird/js/release/promise.js:432:57)
    at Promise._settlePromiseFromHandler (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/bluebird/js/release/promise.js:524:17)
    at Promise._settlePromise (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/bluebird/js/release/promise.js:569:18)
    at Promise._settlePromise0 (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/bluebird/js/release/promise.js:614:10)
    at Promise._settlePromises (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/bluebird/js/release/promise.js:693:18)
    at Promise._fulfill (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/bluebird/js/release/promise.js:638:18)
    at Promise._resolveCallback (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/bluebird/js/release/promise.js:432:57)
    at Promise._settlePromiseFromHandler (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/bluebird/js/release/promise.js:524:17)
    at Promise._settlePromise (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/bluebird/js/release/promise.js:569:18)
    at Promise._settlePromise0 (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/bluebird/js/release/promise.js:614:10)
    at Promise._settlePromises (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/bluebird/js/release/promise.js:693:18)
    at Promise._fulfill (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/bluebird/js/release/promise.js:638:18)
    at Promise._settlePromise (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/bluebird/js/release/promise.js:582:21)
    at Promise._settlePromise0 (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/bluebird/js/release/promise.js:614:10)
    at Promise._settlePromises (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/bluebird/js/release/promise.js:693:18)
    at Promise._fulfill (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/bluebird/js/release/promise.js:638:18)
    at Promise._resolveCallback (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/bluebird/js/release/promise.js:454:14)
    at Promise._settlePromiseFromHandler (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/bluebird/js/release/promise.js:524:17)
    at Promise._settlePromise (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/bluebird/js/release/promise.js:569:18)
    at Promise._settlePromise0 (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/bluebird/js/release/promise.js:614:10)
    at Promise._settlePromises (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/bluebird/js/release/promise.js:693:18)
    at Promise._fulfill (/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/bluebird/js/release/promise.js:638:18)
    at /Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/bluebird/js/release/nodeback.js:42:21
    at /Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/graceful-fs/graceful-fs.js:121:16
    at /Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/node_modules/graceful-fs/graceful-fs.js:43:10
    at FSReqWrap.oncomplete (fs.js:135:15)

Resources

Here are some good links and docs I've found re: upgrading to v4 for plugins / loaders

@thescientist13
Copy link
Collaborator Author

thescientist13 commented Mar 12, 2018

So I have been banging my head against this thinking its been something to do with migrating to the hooks API (could still be an issue there, just got stuck somewhere sooner along the path it seems).

I have determined that (possibly due to webpack-cli being moved out of core webpack?) the upgrade to v4 is "breaking" tests by not actually generating a build into the build directory anymore.

In this branch, I have only updated webpack to v4 and commented all the other loaders and plugins out of the test webpack config, as well as the assertions within the generate-css spec file, and while mocha runs and the tests pass, there is no output to the filesystem.

describe('HtmlCriticalWebpackPlugin Cases: Generate Critical CSS', () => {
  const buildDirectory = path.resolve(__dirname, 'build');

  describe('minimum configuration', () => {

    it('should generate the expected critical inline <style> tag', (done) => {
      webpack(webpackConfig, () => {
        // const indexHtmlString = fs.readFileSync(`${buildDirectory}/index.html`, {encoding: 'utf8'});
        // const indexHtmlDom = new JSDOM(indexHtmlString);
        // const inlineStyleTags = indexHtmlDom.window.document.querySelectorAll('style');
        
        // assert.equal(inlineStyleTags.length, 1);
        // assert.equal(inlineStyleTags[0].getAttribute('type'), 'text/css');

        done();
      });
    });

    //etc
  })
})
$ npm test

> html-critical-webpack-plugin@1.1.0 test /Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin
> rimraf ./test/cases/**/build/** && mocha ./test/**/*.spec.js

spec webpackConfig { mode: 'production',
  entry:
   { index: '/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/test/cases/generate-critical-css/index.js',
     main: '/Users/owenbuckley/Workspace/github/forks/html-critical-webpack-plugin/test/cases/generate-critical-css/main.js' },
  plugins: [] }


  HtmlCriticalWebpackPlugin Cases: Generate Critical CSS
    minimum configuration
      ✓ should generate the expected critical inline <style> tag (428ms)
      - should generate the expected critical <link> tag
      - should generate the expected critical <noscript> tag

  HtmlCriticalWebpackPlugin
    webpack hooks
      ✓ HtmlCriticalWebpackPlugin has the required apply method
      ✓ HtmlCriticalWebpackPlugin has the required emit method


  3 passing (433ms)
  2 pending

screen shot 2018-03-12 at 1 50 26 pm

By comparison, using the webpack-cli directly shows us output we would expect if we didn't have a loader configured for CSS

$ ./node_modules/.bin/webpack-cli --config ./test/cases/generate-critical-css/webpack.config.js
Hash: 4d2d7501158ffb5ed2af
Version: webpack 4.1.1
Time: 94ms
Built at: 2018-3-12 14:19:20
 2 assets
Entrypoint index = index.js
Entrypoint main = main.js
   [0] ./test/cases/generate-critical-css/main.css 200 bytes {0} [built] [failed] [1 error]
   [1] ./test/cases/generate-critical-css/main.js 101 bytes {0} [built]
   [2] ./test/cases/generate-critical-css/index.css 226 bytes {1} [built] [failed] [1 error]
   [3] ./test/cases/generate-critical-css/index.js 104 bytes {1} [built]

ERROR in ./test/cases/generate-critical-css/main.css
Module parse failed: Unexpected token (1:0)
You may need an appropriate loader to handle this file type.
| .card {
|   background: none !important;
|   border: none !important;
 @ ./test/cases/generate-critical-css/main.js 3:0-20

ERROR in ./test/cases/generate-critical-css/index.css
Module parse failed: Unexpected token (1:0)
You may need an appropriate loader to handle this file type.
| .lazyload-wrapper .card-img {
|   border-radius: 0 !important;
|   min-height: 233px!important;
 @ ./test/cases/generate-critical-css/index.js 3:0-21

@thescientist13
Copy link
Collaborator Author

thescientist13 commented Mar 12, 2018

I figured out the issue why webpack wasn't outputting files ☝️ it was because i had a JS style comment in index.css 😕

.fade-appear.fade-appear-active {
  opacity: 1;
  transition: opacity 600ms ease-in; //ms should match the value of transitionAppearTimeout
}

changed it to /* .... */ and it's working (i.e. compiles a build and outputs files).

This PR is now ready for review.

Additional considerations as other PR(s) most likely:

  1. Convert plugin to ES6 Class syntax?
  2. Set a mode option in the root webpack.config.js when building, i.e. yarn run build?
  3. Should some linting be added, i.e. ESLint?
  4. Create a release task that can lint, run tests, and build?

@thescientist13 thescientist13 changed the title webpack v4 compatibility upgrade [WIP] webpack v4 compatibility upgrade Mar 12, 2018
@anthonygore
Copy link
Owner

Great work on this, @thescientist13

A few comments:

  • The test should generate the expected critical inline <style> tag is timing out for me.
  • I noticed in test/cases/generate-critical-css/main.css there are some invalid colors e.g. $gold. I think this was from your previous PR.
  • A small thing, but, when we identify the plugin it looks like the convention it to use kebab case so in index.js 'HtmlCriticalWebpackPlugin' should probably be 'html-critical-webpack-plugin'

Regarding your other suggestions, I'm a yes to all of those. A caveat about point 1, though, we'll need to find out the minimum supported version of Node for Webpack v4 and ensure classes are supported. Or transpile.

@anthonygore
Copy link
Owner

What will we do about backwards compatibility? My thinking is that we tell people to use the previous version. If you agree, perhaps include an update to README.

Also, I think we should we bump the version to 2.0.0 in this PR.

@thescientist13
Copy link
Collaborator Author

thanks for the feedback @anthonygore , I'll put some into this today.

@thescientist13
Copy link
Collaborator Author

thescientist13 commented Mar 26, 2018

Made some updates, let me know your thoughts @anthonygore

The test should generate the expected critical inline <style> tag is timing out for me.

I think this is probably just .a race condition and hitting the default mocha timeout, so I bumped the mocha timeout to 5000ms in package.json, let me know if that helps on your end.

I noticed in test/cases/generate-critical-css/main.css there are some invalid colors e.g. $gold. I think this was from your previous PR.

Good catch! I changed those instances to just normal hex colors

A small thing, but, when we identify the plugin it looks like the convention it to use kebab case so in index.js 'HtmlCriticalWebpackPlugin' should probably be 'html-critical-webpack-plugin'

Not that I have a strong preference one way or the other, but the docs and guides I followed seemed to
favor CamelCase

Regarding your other suggestions, I'm a yes to all of those. A caveat about point 1, though, we'll need to find out the minimum supported version of Node for Webpack v4 and ensure classes are supported. Or transpile.

webpack v4 dropped support for Node <= v4.
https://github.com/webpack/webpack/releases/tag/v4.0.0

and now supports >= 6, which has support for Class, so need to transpile 👌
https://node.green/#ES2015-functions-class

Made an issue for tracking all the misc. refactoring items unrelated to this PR - #13

@thescientist13
Copy link
Collaborator Author

Also, not sure if this is the PR we want to introduce mini-css-extract-webpack-plugin with, but I am happy to include it here.

@anthonygore
Copy link
Owner

Unfortunately the failing test is not a race condition. When I inspected the outputted HTML, there's no style tag! I'm not sure why the tests don't correctly fail, either, they just timeout.

I'm cool with CamelCase if that's a convention.

All the rest is fine, too.

@anthonygore
Copy link
Owner

Actually, I just tried to run the tests on the master branch and it's the same problem.

I haven't investigated deeply, but I did try to log any errors from the API i.e.:

webpack(webpackConfig, (err, stats) => {
  console.log(err);
});

But there are no errors. Strange.

@thescientist13
Copy link
Collaborator Author

thescientist13 commented Mar 27, 2018

@anthonygore
What version of Node are you on? I am on v8.9.4, but I would at least see if you are on something >= 6.x (minimum version supported by webpack v4) and see if that helps. 🤔

@anthonygore
Copy link
Owner

I tried node versions 4, 6, 8 and 9....same problem with all

@thescientist13
Copy link
Collaborator Author

thescientist13 commented Mar 28, 2018

@anthonygore
I started a CircleCI build on my own fork PR and seems to corroborate the issue (please confirm if it is similar to what you are seeing (I branched off master)

will continue to investigate. For the record, I am using OSX.

@anthonygore
Copy link
Owner

Yes, OSX for me too

@anthonygore
Copy link
Owner

anthonygore commented May 12, 2018

Hey @thescientist13, after your great work getting the docker environment created, I think we're almost ready to merge this. What I think needs to be done is:

  • Resolve conflicts
  • Bump version of plugin to 2.0
  • Add engines to package.json and ensure Node >6 is used

[edit]

Actually...

I don't think we should merge this unless it includes mini-css-extract-plugin. Since EWTP is not going to be supported by Webpack 4, we'll have instant problems. What do you think?

@thescientist13
Copy link
Collaborator Author

@anthonygore
Agreed on deprecating ETWP. I'll get this PR all fixed up today. 👍

@thescientist13
Copy link
Collaborator Author

thescientist13 commented May 12, 2018

All set for review @anthonygore !

Question, should this be updated?

Had a question about the build task also (let me know if a new issue makes more sense). Could you explain a little more what it's used for? From my perspective, I think it might just be sufficient to do this in package.json?

"main": "index.js",

I'm not sure how much transpiling of node specific packages is needed in most use cases, but I think it's generally become standard practice to let consumers transpile if they need to, and let authors just publish the source. Let me know your thoughts!

@anthonygore anthonygore merged commit b89192b into anthonygore:master May 14, 2018
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.

anticipated changes needed for webpack v4 support?
2 participants