(Draft) Replace Browserify with Webpack (Draft) (#2461) by rizwanmustafa

* Replaced browserify with webpack

* Modified gulpfile and webpack config

* Removed attempts of using undefined variables and functions

* fixed some incorrect changes

* setfunbox fix

* Added fallback for crypto-browserify and stream-browserify

* added circular dependency detection

* Created production tasks for gulp and updated webpack config

* fixed circular dependency in misc

* not failing on circular dependency

* Removed unused imports

* Added babel loader and plugins to webpack

* Removed unused dependencies and removed babel's plugins

* Workaround for test logic import in random quote

* Created a separate webpack config file for production

* Changed relative paths to absolute ones in webpack

* Added colored output for circular import number

* Removed comment from .eslintrc.json

* Added eslint plugin to webpack

* Moved 'buffer' and 'stream-browserify' to devDependencies

* Started using promises in webpack tasks

* Removed unused dependencies

* Updated package-lock.json

* Removed eslint plugin from webpack and added circular dependency detection in dev config as well

* Removed unrelated changes

* Updated production build command

* Added ability for webpack to be run with typescript conversion of project in process

* added gulp typscript dev dependency

* using const

* modified console logs on circular imports

* missing dev dependency

Co-authored-by: Miodec <bartnikjack@gmail.com>
This commit is contained in:
Rizwan Mustafa 2022-02-12 18:47:36 +05:00 committed by GitHub
parent ddaf20e771
commit 1877cc31e7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 4674 additions and 3903 deletions

View file

@ -28,7 +28,7 @@
// "parser": "@typescript-eslint/parser",
"rules": {
"json/*": ["error"],
"indent": ["off"], //handled by prettier
"indent": ["off"],
"linebreak-style": ["error", "unix"],
"quotes": [
"error",

View file

@ -1,22 +1,21 @@
const { task, src, dest, series, watch } = require("gulp");
// const axios = require("axios");
const browserify = require("browserify");
const babelify = require("babelify");
const concat = require("gulp-concat");
const del = require("del");
const source = require("vinyl-source-stream");
const buffer = require("vinyl-buffer");
const vinylPaths = require("vinyl-paths");
const eslint = require("gulp-eslint-new");
var sass = require("gulp-sass")(require("dart-sass"));
const sass = require("gulp-sass")(require("dart-sass"));
const replace = require("gulp-replace");
const uglify = require("gulp-uglify");
const through2 = require("through2");
const tsify = require("tsify");
const { webpack } = require("webpack");
const webpackDevConfig = require("./webpack.config.js");
const webpackProdConfig = require("./webpack-production.config.js");
const ts = require("gulp-typescript");
// sass.compiler = require("dart-sass");
let eslintConfig = "../.eslintrc.json";
let tsEslintConfig = "../ts.eslintrc.json";
let tsProject = ts.createProject("tsconfig.json");
// console.log(tsProject.src())
task("clean", function () {
return src(["./public/"], { allowEmpty: true }).pipe(vinylPaths(del));
@ -36,35 +35,40 @@ task("lint-json", function () {
.pipe(eslint.failAfterError());
});
task("browserify", function () {
const b = browserify({
entries: "./src/js/index.js",
//a source map isn't very useful right now because
//the source files are concatenated together
debug: false,
task("copy-src-contents", function () {
return src("./src/js/**").pipe(dest("./dist/"));
});
task("transpile-ts", function () {
return tsProject.src().pipe(tsProject()).js.pipe(dest("dist"));
});
task("webpack", async function () {
return new Promise((resolve, reject) => {
webpack(webpackDevConfig, (err, stats) => {
if (err) {
return reject(err);
}
if (stats.hasErrors()) {
return reject(new Error(stats.compilation.errors.join("\n")));
}
resolve();
});
});
let ret = b
.transform(
babelify.configure({
presets: ["@babel/preset-env"],
plugins: ["@babel/transform-runtime"],
})
)
.plugin(tsify)
.bundle()
.pipe(source("monkeytype.js"))
.pipe(buffer());
});
if (process.argv[4] === "production") {
ret = ret.pipe(
uglify({
mangle: false,
})
);
}
ret = ret.pipe(dest("./public/js"));
return ret;
task("webpack-production", async function () {
return new Promise((resolve, reject) => {
webpack(webpackProdConfig, (err, stats) => {
if (err) {
return reject(err);
}
if (stats.hasErrors()) {
return reject(new Error(stats.compilation.errors.join("\n")));
}
resolve();
});
});
});
task("static", function () {
@ -116,7 +120,23 @@ task(
series(
"lint",
"lint-json",
"browserify",
"copy-src-contents",
"transpile-ts",
"webpack",
"static",
"sass",
"updateSwCacheName"
)
);
task(
"compile-production",
series(
"lint",
"lint-json",
"copy-src-contents",
"transpile-ts",
"webpack-production",
"static",
"sass",
"updateSwCacheName"
@ -125,8 +145,12 @@ task(
task("watch", function () {
watch("./src/sass/**/*.scss", series("sass"));
watch(["./src/js/**/*.js", "./src/js/**/*.ts"], series("lint", "browserify"));
watch(
["./src/js/**/*.js", "./src/js/**/*.ts"],
series("lint", "copy-src-contents", "transpile-ts", "webpack")
);
watch("./static/**/*.*", series("lint-json", "static"));
});
task("build", series("clean", "compile"));
task("build-production", series("clean", "compile-production"));

File diff suppressed because it is too large Load diff

View file

@ -5,7 +5,7 @@
"private": true,
"scripts": {
"build": "npx gulp build",
"build:live": "npx gulp build --option production",
"build:live": "npx gulp build-production",
"start:dev": "npm run build && concurrently --kill-others \"npx gulp watch\" \"firebase serve --only hosting\"",
"deploy:live": "npm run build:live && firebase deploy -P live --only hosting"
},
@ -13,32 +13,35 @@
"npm": "8.1.2"
},
"devDependencies": {
"@babel/core": "^7.12.3",
"@babel/plugin-transform-runtime": "^7.12.1",
"@babel/preset-env": "^7.12.1",
"babel-eslint": "^10.1.0",
"babelify": "^10.0.0",
"browserify": "^17.0.0",
"@babel/core": "^7.17.2",
"@babel/plugin-transform-modules-commonjs": "^7.16.8",
"@babel/plugin-transform-runtime": "^7.17.0",
"@babel/preset-env": "^7.16.11",
"babel-loader": "^8.2.3",
"buffer": "^6.0.3",
"circular-dependency-plugin": "^5.2.2",
"dart-sass": "^1.25.0",
"del": "^6.0.0",
"eslint-webpack-plugin": "^3.1.1",
"gulp": "^4.0.2",
"gulp-concat": "^2.6.1",
"gulp-eslint": "^6.0.0",
"gulp-eslint-new": "^1.3.0",
"gulp-sass": "^5.0.0",
"gulp-uglify": "^3.0.2",
"gulp-typescript": "^6.0.0-alpha.1",
"stream-browserify": "^3.0.0",
"through2": "^4.0.2",
"tsify": "^5.0.4",
"typescript": "^4.5.5",
"vinyl-buffer": "^1.0.1",
"vinyl-paths": "^3.0.1",
"vinyl-source-stream": "^2.0.0"
"webpack": "^5.68.0"
},
"dependencies": {
"@babel/runtime": "^7.12.5",
"axios": "^0.21.2",
"chart.js": "^2.9.4",
"chartjs-plugin-annotation": "^0.5.7",
"chartjs-plugin-trendline": "^0.2.2",
"crypto-browserify": "^3.12.0",
"dom-to-image": "^2.6.0",
"gulp-replace": "^1.1.3",
"howler": "^2.2.1",

View file

@ -0,0 +1,67 @@
const path = require("path");
const CircularDependencyPlugin = require("circular-dependency-plugin");
let circularImportNum = 0;
module.exports = {
mode: "production",
entry: path.resolve(__dirname, "dist/index.js"),
resolve: {
fallback: {
crypto: require.resolve("crypto-browserify"),
stream: require.resolve("stream-browserify"),
buffer: require.resolve("buffer"),
},
},
module: {
rules: [
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: "babel-loader",
options: {
presets: ["@babel/preset-env"],
plugins: [
"@babel/plugin-transform-runtime",
"@babel/plugin-transform-modules-commonjs",
],
},
},
},
],
},
output: {
path: path.resolve(__dirname, "public/js/"),
filename: "monkeytype.js",
},
plugins: [
// Ensure that there are no circular dependencies
new CircularDependencyPlugin({
exclude: /node_modules/,
include: /./,
failOnError: true,
allowAsyncCycles: false, // Allow async webpack imports
cwd: process.cwd(), // set current working dir for displaying module paths
// `onDetected` is called for each module that is cyclical
onDetected({ module: _webpackModuleRecord, paths }) {
// `paths` will be an Array of the relative module paths that make up the cycle
// `module` will be the module record generated by webpack that caused the cycle
circularImportNum += 1;
console.log(
"\u001b[31mCircular import found: \u001b[0m" +
paths.join("\u001b[31m -> \u001b[0m")
);
},
// `onEnd` is called before the cycle detection ends
onEnd() {
let coloredImportNum = "";
if (circularImportNum === 0)
coloredImportNum = `\u001b[32m${circularImportNum}\u001b[0m`;
else coloredImportNum = `\u001b[31m${circularImportNum}\u001b[0m`;
console.log(`Found ${coloredImportNum} circular imports`);
if (circularImportNum > 0) process.exit(1);
},
}),
],
};

View file

@ -1,14 +1,17 @@
const path = require("path");
const CircularDependencyPlugin = require("circular-dependency-plugin");
let circularImportNum = 0;
module.exports = {
mode: "development", // Change to 'production' for production
devtool: false, // no SourceMap
entry: "./src/js/index.js",
devtool: false,
entry: path.resolve(__dirname, "dist/index.js"),
resolve: {
fallback: {
crypto: require.resolve("crypto-browserify"),
stream: require.resolve("stream-browserify"),
buffer: require.resolve("buffer"),
},
},
output: {
@ -16,30 +19,30 @@ module.exports = {
filename: "monkeytype.js",
},
plugins: [
// Ensure that there are no circular dependencies
new CircularDependencyPlugin({
// exclude detection of files based on a RegExp
exclude: /node_modules/,
// include specific files based on a RegExp
include: /./,
// add errors to webpack instead of warnings
failOnError: false,
// allow import cycles that include an asyncronous import,
// e.g. via import(/* webpackMode: "weak" */ './file.js')
allowAsyncCycles: false,
// set the current working directory for displaying module paths
cwd: process.cwd(),
onStart() {
console.log("start detecting webpack modules cycles");
},
failOnError: true,
allowAsyncCycles: false, // Allow async webpack imports
cwd: process.cwd(), // set current working dir for displaying module paths
// `onDetected` is called for each module that is cyclical
onDetected({ module: _webpackModuleRecord, paths, compilation }) {
onDetected({ module: _webpackModuleRecord, paths }) {
// `paths` will be an Array of the relative module paths that make up the cycle
// `module` will be the module record generated by webpack that caused the cycle
compilation.errors.push(new Error(paths.join(" -> ")));
circularImportNum += 1;
console.log(
"\u001b[31mCircular import found: \u001b[0m" +
paths.join("\u001b[31m -> \u001b[0m")
);
},
// `onEnd` is called before the cycle detection ends
onEnd() {
console.log("end detecting webpack modules cycles");
let coloredImportNum = "";
if (circularImportNum === 0)
coloredImportNum = `\u001b[32m${circularImportNum}\u001b[0m`;
else coloredImportNum = `\u001b[31m${circularImportNum}\u001b[0m`;
console.log(`Found ${coloredImportNum} circular imports`);
},
}),
],

2997
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -20,6 +20,7 @@
"@types/jquery": "^3.5.13",
"@typescript-eslint/eslint-plugin": "^5.11.0",
"@typescript-eslint/parser": "^5.11.0",
"babel-loader": "^8.2.3",
"circular-dependency-plugin": "^5.2.2",
"concurrently": "5.3.0",
"eslint": "8.8.0",
@ -30,6 +31,7 @@
"eslint-plugin-node": "11.1.0",
"eslint-plugin-promise": "5.1.0",
"eslint-plugin-require-path-exists": "1.1.9",
"gulp-typescript": "^6.0.0-alpha.1",
"husky": "4.3.0",
"prettier": "2.1.2",
"pretty-quick": "3.1.0",