使用 webpack、babel 和 eslint 设置一个 ES6 JavaScript 项目
目录 -
- 设置
- 造型
- 绒毛
每当有人学习一门新的编程语言时,他们的第一个程序有99%的概率是“ Hello World”程序。在这个经典的程序中,他们需要Hello World在屏幕/控制台上打印出“Hello World”。根据编程语言的不同,这个程序可能只有一行,也可能有多行,仅仅是为了打印这“Hello World”。
在 Javascript 时代(4-5 年前),人们只需创建一个包含此内容的 HTML 文件,然后在浏览器中打开它,即可在浏览器窗口(以及浏览器控制台)中看到“Hello World”打印出来。
<!DOCTYPE html>
<html>
<head>
<title>Hello World</title>
</head>
<body>
<p>Hello World</p>
<script>
console.log('Hello World');
</script>
</body>
</script>
但随着 JavaScript 生态系统的成熟,这个过程变得稍微复杂了一些(这是好事)。在本教程中,您将了解如何设置此类项目。
假设
- 你懂JavaScript(最好也懂一些ES6)。
- 您的系统上
nodejs已安装(教程)。npm
完整的代码可在https://github.com/brijeshb42/hello-world-tutorial获取。
第一部分
打开终端应用程序或命令提示符,并cd切换到您想要创建项目的目录。假设项目文件夹hello-world位于磁盘上的某个目录中。现在输入以下命令 -
cd hello-worldnpm init --y
这将在目录中创建一个package.json文件hello-world。package.json该文件位于您的项目中,用于nodejs跟踪npm已安装的软件包和项目元数据。您的文件package.json可能如下所示:
{
"name": "hello-world",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
现在添加 webpack 和 dev-server -
npm install webpack@3.11.1 webpack-dev-server --save-dev
截至撰写本文时,已安装的 webpack 版本为3.11.1。
编辑:正如评论中指出的那样,版本号已经添加,
Patrick Cole因为自本教程发布以来,webpack版本 4 已经发布,其配置略有不同,可能会破坏本教程的设置。
在项目文件夹内创建一个src目录,然后index.js在该目录内创建一个文件。
mkdir srcecho "console.log('Hello world');" > src/index.js
这是我们的 Hello World 程序,运行时会Hello world在浏览器控制台中打印内容。
此时,您可以开始编写 webpack 配置文件,将您的文件打包以供浏览器加载。
在项目文件夹中创建一个webpack.config.js文件,内容如下。webpack 会使用此文件读取您的配置并据此构建项目。
const path = require('path');
module.exports = {
entry: {
bundle: './src/index.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
}
};
现在,您可以运行此命令,让 webpack 加载入口文件,并dist在项目目录的根目录中创建一个打包的 js 文件。
./node_modules/.bin/webpack
这条构建命令会将所有依赖项打包,并bundle.js根据outputwebpack 配置文件中的选项创建一个文件。运行此命令后,您可以在 `/etc/webpack.js` 目录bundle.js下看到一个文件dist。您现在还不能加载这个 js 文件,因为您首先需要一个 html 文件。浏览器会加载 html 文件,然后 html 文件才会加载 js 文件。
您可以手动在 `/etc/webpack.js` 目录下创建一个index.html包含此内容的文件dist。
<script src="./bundle.js"></script>
这是加载和运行我们打包好的 JS 所需的最小 HTML 代码量。现在您可以双击此 HTML 文件,它会在浏览器中打开。您可以使用 `console.log` 打开浏览器控制台CMD/CTRL + SHIFT + I来查看输出。接下来,我们来看一种更好的方法,您无需编写 HTML 文件。
npm install html-webpack-plugin --save-dev
这是一个 webpack 插件,它可以自动生成包含所有已生成 JavaScript 文件正确引用的index.html文件。要使用此插件,请更新您的webpack 配置:distwebpack.config.js
const path = require('path');
+ const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
bundle: './src/index.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
- }
+ },
+ plugins: [
+ new HtmlWebpackPlugin()
+ ]
};
之后,您可以再次运行构建命令 -
./node_modules/.bin/webpack
现在,该目录index.html下会创建一个额外的文件,dist其中包含要包含的正确脚本标签bundle.js。现在可以直接在浏览器中打开该文件,其功能与之前相同,只是您无需自行创建。
为了简化构建命令,我们创建一个别名,package.json这样您只需输入命令npm run build即可打包文件。更新您的package.json-
{
"name": "hello-world",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"html-webpack-plugin": "^2.30.1",
"webpack": "^3.11.0",
"webpack-dev-server": "^2.11.1"
- }
+ },
+ "scripts": {
+ "build": "webpack"
+ }
}
目前,webpack 只会打包文件然后退出。如果您只想打包并部署到本地或远程服务器,这当然很好。但在开发过程中,这种方式很快就会让人感到沮丧。为了解决这个问题,您可以使用 webpack,webpack-dev-server它会持续监控文件更改,并在浏览器中立即刷新页面。它还会启动一个开发服务器,dist这样 HTML 文件就会从服务器而不是文件系统加载(以防您在 JavaScript 中使用了 Ajax,而 Ajax 在文件系统中无法正常工作)。您可以使用以下命令安装 webpack:
npm install webpack-dev-server
这将启动开发服务器,并以 ` dist<default_url>` 作为基本目录。默认 URL 为 `<default_url>` http://localhost:8080。在浏览器中打开此 URL 将加载该index.html文件并Hello World在控制台中记录日志。现在,如果您将 `<default_url>` 中的控制台日志从 `<default_url>` 更新为 ` Hello World<default_url>` Hi World,src/index.js则会webpack-dev-server自动重新加载浏览器,您将能够看到新的输出。
./node_modules/.bin/webpack-dev-server --content-base dist
让我们也把它添加为别名package.json-
{
"name": "hello-world",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"html-webpack-plugin": "^2.30.1",
"webpack": "^3.11.0",
"webpack-dev-server": "^2.11.1"
},
"scripts": {
"build": "webpack",
+ "dev": "webpack-dev-server --content-base dist"
}
}
现在运行程序npm run dev将webpack-dev-server自动重新加载更改。
目前,你的 JavaScript 代码还不能使用 ES6 语法。让我们来添加对 ES6 的支持。这可以通过使用 Babel 来实现babel。为了在构建过程中添加 Babel 支持,我们首先需要安装它。这babel-loader需要babel-core安装 Babel。为了支持 ES6/7/8/* 语法,你需要添加 Babel babel-preset-env。在项目文件夹的终端中运行以下命令:
npm install babel-core babel-loader babel-preset-env --save-dev
首先.babelrc在项目目录中创建一个文件,以便 Babel 可以加载其配置。将以下内容添加到该文件中:
{
"presets": [[
"env", {
"targets": {
"browsers": ["Chrome >= 55"]
}
}
]]
}
这种配置是特意设计的,以便您可以在dist目录中查看打包后的 js 文件,并了解您的 ES6 代码是如何被转译的。随着浏览器对越来越多的 ES6 特性的支持,babel现在不再盲目地转译所有代码,而是智能地识别哪些特性是原生支持的,并避免转译这些部分。这可以减小整体打包体积。
如果您不关心浏览器版本,那么最简单的配置方法应该是这样的:
{
"presets": ["env"]
}
现在让我们先指示webpack使用 Babel 转译这些js文件。
const path = require('path');
+ const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: `{
bundle: './src/index.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
plugins: [
new HtmlWebpackPlugin()
- ]
+ ],
+ module: {
+ rules: [{
+ test: /\.js$/,
+ exclude: /node_modules/,
+ use: 'babel-loader'
+ }]
+ }
};
创建一个新文件src/message.js并添加以下内容 -
export default "Hello World";
现在修改代码src/index.js,使用 ES6 中最简单的导入功能 -
import message from './message';
console.log(message);
上面的代码使用了 ES6 模块语法。现在运行npm run dev会生成一个更新后的包(尽管输出结果相同),你可以在浏览器控制台中测试它。
以上总结了教程的第一部分,其中您已经设置了一个最简单的(真的非常简单的)javascript项目,使用webpack进行打包,并集成babel将es6转译为es5。
第二部分
现在,我们进入教程的第二部分,我们将设置 webpack 来导入css文件。通过这种方式,您可以直接在 JavaScript 文件中引入样式。
首先,我们来修改一下src/index.js,让它在页面上显示一些文本,而不是仅仅记录到控制台。
import message from './message';
-console.log(message);
+const paragraph = document.createElement('p');
+paragraph.innerHTML = message;
+
+document.body.prepend(paragraph);
这会创建一个p标签,其中导入的内容message作为 html 代码添加到页面中。
现在,让我们p用 CSS 来设置这个标签的样式。这需要 ` css-loader<script>` 和 `<script> ` 标签style-loader。使用以下命令安装它们:`--install-style`
npm install css-loader style-loader --save-dev
为了支持css文件导入,我们更新一下webpack.config.js规则,添加一条新规则,该规则会检查导入的文件是否具有扩展名,并使用 `--`和`--`css解析它。style-loadercss-loader
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: {
bundle: './src/index.js '
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
plugins: [
new HtmlWebpackPlugin()
],
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
use: 'babel-loader'
+ }, {
+ test: /\.css$/,
+ exclude: /node_modules/,
+ use: [
+ {loader: 'style-loader'},
+ {loader: 'css-loader'}
+ ]
+ }]
}
};
现在创建一个 CSS 文件src/index.css并设置p标签样式 -
p {
color: red;
}
将此 CSS 文件导入src/index.css-
import message from './message';
+import './index.css';
const paragraph = document.createElement('p');
paragraph.innerHTML = message;
document.body.prepend(paragraph);
现在,使用 `--restart` 命令重启开发服务器npm run dev。你会看到页面现在显示Hello World为红色。如果你在 `--restart` 文件中将颜色从红色更改为蓝色index.css,页面将重新加载并显示新样式。要在不实际重新加载页面的情况下查看新样式,请修改开发服务器命令package.json。
{
"name": "hello-world",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack",
- "dev": "webpack-dev-server --content-base dist"
+ "dev": "webpack-dev-server --content-base dist --hot"
},
"keywords": [],
"author": "" ,
"license": "ISC",
"devDependencies": {
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-env": "^1.6.1",
"css-loader": "^0.28.9",
"html-webpack-plugin": "^2.30.1",
"style-loader": "^0.20.2",
"webpack": "^3.11.0",
"webpack-de v-server": "^2.11.1"
}
}
这在 webpack 中实现了热模块替换,无需完全重新加载页面即可显示代码中的新更改(在 `<head>`css或`<body>` 或任何 webpack 能够加载的文件)。使用 `npm restart server` 重启服务器,然后尝试更改 CSS 中 `<div>` 元素的颜色。你会注意到,即使页面没有实际重新加载,颜色也会发生变化。jsnpm run devp
npm run build如果你尝试在目录中运行构建命令,dist你会发现没有生成任何 CSS 文件。这是因为 webpack 会将样式作为字符串添加到 JavaScript 包中,并通过创建style标签将这些样式应用到页面中。这在开发阶段没有问题。但在部署过程中,最佳实践是将 CSS 文件包含在head标签中,这样在 JavaScript 加载期间页面外观就不会受到影响。为了解决这个问题,我们将使用 `<script>`标签,extract-text-webpack-plugin它会在构建过程中将所有导入的 CSS 提取到一个单独的文件中。在此之前,我们先来配置 webpack 以使其能够识别 `<script>`标签development和production`<script>` 标签。
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
+ const env = process.env.NODE_ENV || 'development';
+ const isDev = env === 'development';
+ const isProd = env === 'production';
module.exports = {
entry: {
bundle: './src/index.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
plugins: [
new HtmlWebpackPlugin()
],
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
use: 'babel-loader'
}, {
test: /\.css$/,
exclude: /node_modules/,
use: [
{loader: 'style-loader'},
{loader: 'css-loader'}
]
}]
}
};
并修改package.json为在生产模式下运行构建命令,在开发模式下运行开发服务器。
{
"name": "hello-world",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
- "build": "webpack",
- "dev": "webpack-dev-server --content-base dist --hot"
+ "build": "NODE_ENV=production webpack",
+ "dev": "NODE_ENV=development webpack-dev-server --content-base dist --hot"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-env": "^1.6.1",
"css-loader": "^0.28.9",
"extract-text-webpack-plugin": "^3.0.2",
"html-webpack-plugin": "^2.30.1",
"style-loader": "^0.20.2",
"webpack": "^3.11.0",
"webpack-dev-server": "^2.11.1"
}
}
现在extract-text-webpack-plugin使用 - 进行安装
npm install extract-text-webpack-plugin --save-dev
并更新webpack.config.js-
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
+const ExtractTextPlugin = require('extract-text-webpack-plugin');
const env = process.env.NODE_ENV || 'development';
const isDev = env === 'development';
const isProd = env === 'production';
+const extractCss = new ExtractTextPlugin({
+ filename: 'index.css',
+ disable: isDev
+});
module.exports = {
entry: {
bundle: './src/index.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
plugins: [
- new HtmlWebpackPlugin()
+ new HtmlWebpackPlugin(),
+ extractCss
],
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
use: 'babel-loader'
}, {
test: /\.css$/,
exclude: /node_modules/,
- use: [
- {loader: 'style-loader'},
- {loader: 'css-loader'}
- ]
+ use: extractCss.extract({
+ use:[
+ {loader: 'css-loader'}
+ ],
+ fallback: 'style-loader'
+ })
}]
}
};
在开发模式下,此功能会被禁用extractCss,此时style使用标签来应用 CSS。在生产模式下,extractCss插件会将所有css来自捆绑包的 CSS 提取到它们自己的文件中,这些文件的名称根据声明时使用js的值而定。filenameextractCss
现在运行npm run build将在dist- bundle.js、index.css和 中创建 3 个文件index.html。
更新 - 添加 SCSS 支持
让我们scss为 webpack 配置文件添加解析支持。为此,您需要 ,sass-loader而 又需要node-sass。使用以下命令安装这些:
npm install node-sass sass-loader --save-dev
现在,更新webpack.config.jswebpack,使其知道如何处理导入的 scss 文件 -
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const env = process.env.NODE_ENV || 'development';
const isDev = env === 'development';
const isProd = env === 'production';
-const extractCss = new ExtractTextPlugin({
+const extractScss = new ExtractTextPlugin({
filename: 'index.css',
disable: isDev
});
module.exports = {
entry: {
bundle: './src/index.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
plugins: [
new HtmlWebpackPlugin(),
- extractCss
+ extractScss
],
module: {
rules: [{
test: /\.js$/,
exclude: /node_modules/,
use: 'babel-loader'
}, {
- test: /\.css$/,
+ test: /(\.css|\.scss)$/,
exclude: /node_modules/,
- use: extractCss.extract({
+ use: extractScss.extract({
use:[
- {loader: 'css-loader'}
+ {loader: 'css-loader'},
+ {loader: 'sass-loader'}
],
fallback: 'style-loader'
})
}]
}
};
现在来测试一下,重命名index.css并index.scss使用基本的 SCSS 嵌套更新其内容 -
body {
p {
color: red;
}
}
更新导入内容index.js-
import message from './message';
-import './index.css';
+import './index.scss';
const paragraph = document.createElement('p');
paragraph.innerHTML = message;
document.body.prepend(paragraph);
运行此程序npm run dev并在浏览器中打开该网址进行测试。
css本部分结束了导入和scss文件的使用js。
第三部分
随着项目代码库规模的扩大,如果在早期阶段没有妥善处理,就很难维护严格的编码规范。此外,随着越来越多的人参与同一个项目,他们可能会带来各自的编码风格,导致不同文件中的代码风格各异,让新开发者难以抉择。使用代码检查工具(linter)可以解决这个问题。它们有助于遵循统一的编码规范。JavaScript 代码检查工具会显示许多有用的信息,例如未使用的变量、缺少分号(在某些项目中这可能不是问题)、代码长度超过最大允许值等等。让我们更新项目,以便eslint在未遵循特定规范时抛出错误。为此,我们需要 `linter`和 ` eslintlisten` eslint-loader。使用以下命令安装它们:
npm install eslint eslint-loader --save-dev
现在更新以告知 webpack 在传递之前webpack.config.js使用-eslint-loaderbabel-loader
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const env = process.env.NODE_ENV || 'development';
const isDev = env === 'development';
const isProd = env === 'production';
const extractScss = new ExtractTextPlugin({
filename: 'index.css',
disable: isDev
});
module.exports = {
entry: {
bundle: './src/index.js'
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js'
},
plugins: [
new HtmlWebpackPlugin(),
extractScss
],
module: {
rules: [{
+ enforce: 'pre',
+ test: /\.js$/,
+ exclude: /node_modules/,
+ use: 'eslint-loader'
+ }, {
test: /\.js$/,
exclude: /node_modules/,
use: 'babel-loader'
}, {
test: /(\.css|\.scss)$/,
exclude: /node_modules/,
use: extractScss.extract({
use:[
{loader: 'css-loader'},
{loader: 'sass-loader'}
],
fallback: 'style-loader'
})
}]
}
};
.eslintrc在项目根目录(与 .js 文件并列)创建一个新文件。在这个文件中,您可以定义自己的自定义规则以及要遵循的package.json解析器。eslint
{
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module"
},
"extends": "eslint:recommended"
}
ecmaVersion允许 ESLint 识别 ES6 特性,sourceType: module并允许使用 `<script>`import和 ` export<script>` 关键字。默认情况下,没有为 `<script>` 设置任何规则eslint。因此,"extends": "eslint:recommended"它告诉eslintESLint 使用默认的推荐规则。
此时,您可以运行命令npm run dev。在控制台中,您会看到两种相同类型的错误——
4:19 error 'document' is not defined no-undef
7:1 error 'document' is not defined no-undef
这表示该变量document未no-undef在任何地方定义(),但仍在使用。这可以通过两种方式解决。要解决此问题,您需要使用该globals键.eslintrc。更新您的.eslintrc-
{
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module"
},
- "extends": "eslint:recommended"
+ "extends": "eslint:recommended",
+. "globals": {
"document": true
}
}
这说明eslint该变量document是全局变量,将由 JS 环境(在本例中为浏览器)提供。现在您可以正常运行而npm run dev不会出现任何错误。您还可以添加一个代码检查命令,以便package.json独立于 webpack 查看代码检查错误。更新package.json-
{
"name": "hello-world",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "NODE_ENV=production webpack",
- "dev": "NODE_ENV=development webpack-dev-server --content-base dist --hot"
+ "dev": "NODE_ENV=development webpack-dev-server --content-base dist --hot",
+ "lint": "eslint ./src --ext .js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-env": "^1.6.1",
"css-loader": "^0.28.9",
"eslint": "^4.18.1",
"eslint-loader": "^2.0.0",
"extract-text-webpack-plugin": "^3.0.2",
"html-webpack-plugin": "^2.30.1",
"node-sass": "^4.7.2",
"sass-loader": "^6.0.6",
"style-loader": "^0.20.2",
"webpack": "^3.11.0",
"webpack-dev-server": "^2.11.1"
}
}
npm run lint现在,无论是否打包项目,您都可以在控制台中运行该命令来检查代码检查错误。这也可以用于 Git 的 pre-commit 钩子,以便eslint在抛出任何错误时阻止提交。该命令eslint ./src --ext .js会eslint检查目录中所有带有扩展src名的文件是否存在错误js。您还可以--fix为该命令添加一个可选选项,该选项会自动尝试修复错误,从而避免您手动修复。
.eslintrc您还可以根据需要,在文件中添加自定义规则。此eslint:recommended选项不允许您console.log在代码中使用(推荐使用日志模块)。您可以添加一条规则,指示eslint在语句中显示警告console.log而不是错误。更新.eslintrc文件 -
{
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module"
},
"extends": "eslint:recommended",
"globals": {
- "document": true
+ "document": true,
+ "console": true
- }
+ },
+ "rules": {
+ "no-console": 1
+ }
}
"no-console": 1指示eslint显示警告而不是错误。其他值包括0(关闭eslint此规则)和2(如果违反此规则则抛出错误)。许多公司使用一些标准的 JavaScript 风格指南(而不是默认的eslint:recommended)。其中之一是 Airbnb 的JavaScript 风格指南,它添加了许多公认的代码检查规则。您可以使用它来代替当前的指南。让我们将其添加到我们的配置中。它需要安装一个额外的eslint-plugin-import依赖项。eslint-config-airbnb-base使用以下命令安装及其依赖项:
npx install-peerdeps --dev eslint-config-airbnb-base
现在更新.eslintrc-
{
- "parserOptions": {
- "ecmaVersion": 6,
- "sourceType": "module"
- },
- "extends": "eslint:recommended",
+ "extends": "airbnb-base",
"globals": {
"document": true,
"console": true
},
"rules": {
"no-console": 1
}
}
airbnb-base内部已parserOptions移除。现在,当你运行该命令时npm run dev,会收到错误提示。
...hello-world/src/message.js
1:16 error Strings must use singlequote quotes
这是因为airbnb-base该程序有一条规则,即字符串使用单引号而不是双引号。npm run lint使用--fix选项运行程序会自动将其更改"为'使用单引号src/message.js。
至此,我们介绍了如何使用该方法eslint来强制执行代码质量。
第 4 部分将更新此项目,开始开发 ReactJS 应用程序。
本文最初发表于bitwiser.in
文章来源:https://dev.to/brijesh/setup-a-es6-javascript-project-using-webpack-babel-and-eslint-1ek3