Use webpack to build files and webpack-dev-server for testing#1068
Use webpack to build files and webpack-dev-server for testing#1068k4b7 merged 24 commits intoKaTeX:masterfrom ylemkimon:webpack
Conversation
Created a webpack entry point for KaTeX, which imports katex.less. As flow[1] and jest[2] doesn't support CSS modules natively, a separate entry point is used and it is not flowtyped. [1] https://gist.github.com/lambdahands/d19e0da96285b749f0ef [2] https://facebook.github.io/jest/docs/en/webpack.html
* Made webpack.config.js export valid webpack configuration * Use: browserify -> webpack babelify -> babel-loader UglifyJS CLI -> UglifyJsPlugin Less CLI -> less-loader cleancss -> cssnano in css-loader build/fonts -> file-loader * Inline CSS(Less) using style-loader and export them using ExtractTextPlugin * Add `watch` npm script calling `webpack --watch`
* Made webpackDevServer export a valid webpack configuration * Compile Less and inline CSS using less-loader and style-loader * Instead of copying files serve files from /static and use file-loader * Remove old server.js and its dependencies
|
CLA signature looks good 👍 |
+ Moved common configurations to webpack.common.js
| // @flow | ||
| const { targets, createConfig } = require('./webpack.common'); | ||
| const path = require('path'); | ||
| const PORT = 7936; |
There was a problem hiding this comment.
Is there any specific reason using the port 7936?
There was a problem hiding this comment.
We wanted to avoid a collision with other services that are usually running in the normal dev environment at Khan Academy.
| $(BUILDDIR)/contrib/mathtex-script-type.min.js: $(BUILDDIR)/mathtex-script-type.js | ||
| $(UGLIFYJS) < $< > $@ | ||
|
|
||
| $(BUILDDIR)/mathtex-script-type.js: mathtex-script-type.js |
There was a problem hiding this comment.
Is outputting mathtex-script-type.js to $(BUILDDIR), not $(BUILDDIR)/contrib, and not including in the distribution archive an intended behavior?
| $(UGLIFYJS) < $< > $@ | ||
|
|
||
| $(BUILDDIR)/contrib/copy-tex.js: copy-tex.js | ||
| $(BROWSERIFY) -t [ babelify ] $< --standalone renderMathInElement > $@ |
There was a problem hiding this comment.
Is exporting the copy-tex module to renderMathInElement, a name also used by auto-render, an intended behavior?
There was a problem hiding this comment.
Thanks for catching this. I guess nobody's been using this as a standalone script.
k4b7
left a comment
There was a problem hiding this comment.
Thanks for the PR. I've used webpack before, but haven't used it for building styles so I have a lot of questions about that.
| use: [{ | ||
| loader: 'file-loader', | ||
| options: { | ||
| name: 'fonts/[name].[ext]', |
There was a problem hiding this comment.
This just copies the files into the fonts folder?
There was a problem hiding this comment.
I've never handled fonts like this before. If we didn't do this we'd need a separate way to serve font files when using the dev server correct?
There was a problem hiding this comment.
@kevinbarabash It loads included font files in the stylesheet(fonts.less) and outputs to fonts/.
There was a problem hiding this comment.
For this to get used, you'd have to import the font into the dependency tree, right? Is that being done?
There was a problem hiding this comment.
@rrandallcainc Yes. Current dependency tree is: katex.wepack.js imports static/katex.less, static/katex.less imports static/fonts.less, and fonts.less imports(using @font-face) font files.
| name: string, // the name of output JS/CSS | ||
| entry: string, // the path to the entry point | ||
| library?: string // the name of the exported module | ||
| |}; |
There was a problem hiding this comment.
Using comments with flow to avoid having to transpile?
webpack.common.js
Outdated
| config.plugins.push(new UglifyJsPlugin({ | ||
| uglifyOptions: { | ||
| output: { | ||
| ascii_only: true, |
There was a problem hiding this comment.
The Makefile used --mangle --beautify ascii_only=true,beautify=false. Does UglifyJsPlugin support the same options?
There was a problem hiding this comment.
@kevinbarabash Yes. mangle is enabled by default and beautify=false was necessary in order to pass ascii_only=true to the CLI(mishoo/UglifyJS#54).
| disable: dev, | ||
| }), | ||
| ], | ||
| devtool: dev && 'inline-source-map', |
| const cssLoader = { | ||
| loader: 'css-loader', | ||
| options: { | ||
| minimize, // cssnano |
There was a problem hiding this comment.
@kevinbarabash cssnano is a CSS minifier equivalent to clean-css and it is included in the css-loader, which can be enabled by passing minimize: true to its options.
Makefile
Outdated
| mkdir -p build | ||
| $(CLEANCSS) -o $@ $< | ||
| mkdir -p build/contrib | ||
| mkdir -p build/fonts |
There was a problem hiding this comment.
Doesn't webpack create the directories it needs if they don't exist?
There was a problem hiding this comment.
@kevinbarabash Yes, it does. Will remove them.
Makefile
Outdated
| @# Since everything in build/contrib and build/fonts is put in the built files, | ||
| @# make sure there's nothing in there we don't want. | ||
| rm -rf build/contrib/* | ||
| rm -rf build/fonts/* |
There was a problem hiding this comment.
I don't if we should just do rm -rf build?
There was a problem hiding this comment.
@kevinbarabash I think preserving other files in build/ is no longer necessary as dev server doesn't generate or use files in build/. Will change to rm -rf build/*
| (To run this example from a clone of the repository, run `npm start` | ||
| in the root KaTeX directory, and then visit | ||
| http://0.0.0.0:7936/contrib/auto-render/index.html | ||
| http://localhost:7936/contrib/auto-render/index.html |
| <meta charset="UTF-8"> | ||
| <title>Auto-render test</title> | ||
| <script src="/katex.js" type="text/javascript"></script> | ||
| <link href="/katex.css" rel="stylesheet" type="text/css"> |
| <title>Copy-tex test</title> | ||
| <script src="/katex.js" type="text/javascript"></script> | ||
| <link href="/katex.css" rel="stylesheet" type="text/css"> | ||
| <link href="./copy-tex.css" rel="stylesheet" type="text/css"> |
There was a problem hiding this comment.
I believe webpack will now inject these with either a script tag (extract plugin) or directly into the JS.
Why is it a partial fix? |
|
I restarted the travis-ci build b/c I was really confused by the output of the previous run. It should be running |
|
@kevinbarabash Currently Travis seems to be not working and backlogged. |
|
@kevinbarabash
As |
to be consistent, avoid confusion with webpack-dev-server and follow webpack configuration naming convention.
+ Add comments regarding function arguments
This reverts commit f6b5091.
| /* eslint no-console:0 */ | ||
| /* global katex */ | ||
|
|
||
| import katex from "katex"; |
There was a problem hiding this comment.
Won't this result in the bundle that's built for auto-render.js also containing all of KaTeX?
| @@ -1,24 +1,22 @@ | |||
| /* global katex */ | |||
| import katex from "katex"; | |||
There was a problem hiding this comment.
Same concern as in auto-render.js.
There was a problem hiding this comment.
@kevinbarabash The module katex is declared as externals in the webpack configuration. As a result, webpack doesn't bundle the KaTeX, but tries to require the module by require("katex") in CJS, define(["katex"], ...) in AMD, and using global variable katex(old behavior) otherwise. Basically, it adds support for module loaders.
ry-randall
left a comment
There was a problem hiding this comment.
This is really exciting to see, thanks for opening!
| use: [{ | ||
| loader: 'file-loader', | ||
| options: { | ||
| name: 'fonts/[name].[ext]', |
There was a problem hiding this comment.
For this to get used, you'd have to import the font into the dependency tree, right? Is that being done?
| @@ -1,61 +1,7 @@ | |||
| const path = require('path'); | |||
| // @flow | |||
| const { targets, createConfig } = require('./webpack.common'); | |||
There was a problem hiding this comment.
Would we want to rename this to webpack.prod.js?
There was a problem hiding this comment.
@rrandallcainc As webpack's default configuration filename is webpack.config.js, if webpack is called without any arguments, production build will be run.
| <title>Copy-tex test</title> | ||
| <script src="/katex.js" type="text/javascript"></script> | ||
| <link href="/katex.css" rel="stylesheet" type="text/css"> | ||
| <link href="./copy-tex.css" rel="stylesheet" type="text/css"> |
There was a problem hiding this comment.
I believe webpack will now inject these with either a script tag (extract plugin) or directly into the JS.
| // Now we need to find an IP the container can connect to. | ||
| // First, install a server component to get notified of successful connects | ||
| app.get("/ss-connect.js", function(req, res, next) { | ||
| devServer.app.get("/ss-connect.js", function(req, res, next) { |
| }; | ||
|
|
||
| module.exports = { | ||
| export default { |
There was a problem hiding this comment.
Is this a breaking change for CJS users?
There was a problem hiding this comment.
@rrandallcainc For dist/katex.js, which is distribution file and entry point of katex module, as webpack exports an UMD module and default export is exposed, I think there'll be no breaking changes.
There was a problem hiding this comment.
(ii)katex.js: transpilers and/or bundlers usesinteropDefault, which imports default export when importing ES6 module
I think there'll be no breaking changes.
@rrandallcainc I'm don't know there is a use case of directly requiring katex.js (from the root), e.g., const katex = require('./node_modules/katex/katex.js);, as it needs transpiling, but in that case, the user has to use .default, e.g., const katex = require('./node_modules/katex/katex.js).default;.
There was a problem hiding this comment.
Hmm, but I still think katex.js serves as the entry point, right? Even though this will be wrapped in a UMD, I think it's going to be a breaking change when requiring the built artifact. This is due to ES6 modules always being named. When CJS users try and import Katex, they'll need to change their import from require('katex') to require('katex').default.
Perhaps I am missing something though.
There was a problem hiding this comment.
@rrandallcainc Webpack has option libraryExport, which configures which module(s) will be exposed via UMD and it is set to default. So requiring katex module(require('katex')) will expose default export and work same.
| @@ -1,106 +0,0 @@ | |||
| /* eslint no-console:0 */ | |||
| "version": "0.10.0-pre", | ||
| "description": "Fast math typesetting for the web.", | ||
| "main": "dist/katex.js", | ||
| "browser": "dist/katex.min.js", |
There was a problem hiding this comment.
@kevinbarabash #1057 is no longer needed, since webpack doesn't use name require and browserify/browserify#374 is not an issue.
Allows webpack to be run from other directories
|
Updated PR description 😄 |
Do not transform modules to commonjs in Babel. However Jest doesn't not support ES6 modules, so transfrom modules to commonjs when NODE_ENV is `test`.
| "env": { | ||
| "test": { | ||
| "plugins": [ | ||
| "transform-es2015-modules-commonjs" |
There was a problem hiding this comment.
This is for Jest, as it doesn't support ES6 modules.
In Babel 6, env configurations doesn't overrides configuration, rather are merged to the root configuration(babel/babel#5276).
There was a problem hiding this comment.
Could you avoid adding this dependency by adding the .default to your imports instead?
There was a problem hiding this comment.
@rrandallcainc Node doesn't support ES6 import/export module syntaxes, so I think adding .default won't help it. Also this plugin is part of babel-preset-es2015, so there won't be any additional dependencies.
|
@ylemkimon thanks for updating the comment at the top. I'm pretty busy this week. I'll try to do another pass on the weekend. |
Changed version range to include IE-compatible version
| @@ -0,0 +1,121 @@ | |||
| // @flow | |||
There was a problem hiding this comment.
It seems it's possible to
(i) use ES6 in webpack.config.js by using the extension .babel.js, which transpiles the file before loading
(ii) put all configurations in one file by webpack.config.js exporting a function, which takes environment variables as an argument and returns the webpack configuration
There was a problem hiding this comment.
I think having the whole config in a single file and using environment variables to control things might be nice. I'm going land this as is though and any additional work could happen in a followup PR.
|
@ylemkimon thanks for listing out the breaking changes. I think the only breaking change that might affect users would be the third one, but my guess would be that most users are using the compiled bundle so this shouldn't be an issue. We can add it to the breaking changes part of the release notes when we do a release. From the "old/new" section:
This sounds scarier than it is b/c the bundle is built in such a way that it exposes a commonjs interface as well as a |
k4b7
left a comment
There was a problem hiding this comment.
LGTM. I'm really happy that we have a more consistent build system. Also, looking forward to being able to experiment with webpack plugins such as ModuleConcatenationPlugin.
|
Sounds great! Just checking: Does |
|
I did the following as a quick check:
|
|
@davidflanagan just let me know that this change "shaved 40Kb off of katex.min.js!" |
Fixes #1063
Fixes partially #929 (webpack-dev-server reloads when
katex.lessis changed)Fixes #692
Fixes #983
browserify(make *.js)webpackbabelifybabel-loaderUglifyJSCLI(make *.min.js)UglifyJsPluginLessCLI, copy .css(make *.css)less-loader,css-loader, andExtractTextPluginclean-cssCLI(make *.min.css)cssnanoincluded in webpackcss-loadermake build/fonts)file-loadermake contriband Makefiles for each contrib)webpack.common.js[1]make build/katex.js build/katex.min.js build/katex.css build/katex.min.css build/fonts build/contribmaketargetwebpack, which doesnpm run build(webpack)makerecompilewebpack --watch(npm run watch)server.js(Removed in #902),webpack-dev-server(webpackDevServer.js)webpack-dev-serverconfiguration(renamed towebpack.dev.js), updated documentationsprestart)style-loader[2]server.jswebpack-dev-serverPossible Breaking Changes:
contribmake contribmake build/contribornpm run build(webpack)build-cssnpm run build-cssmake [.css filename]ornpm run build(webpack)./katex.js(
require('./katex.js))defaultproperty(
require('./katex.js).default)I'm not sure there are use cases of above cases.