前端工程不了解?带你踩坑加爬坑。

原创 前端开发者 随笔 前端 141阅读 27 天前 举报

文中许多步骤会在运行时报错,从错误中分析需要添加的配置,加深印象以及对所添加的每一行配置的理解。

本文将以 React 为例,带你走一次。

创建目录

webpack

安装webpack依赖

修改配置

这是一份最基本的webpack配置:

调整package.json

在package.json中,添加 scipts 如下:

初试build

在命令行中执行

你会看到如下警告:

WARNING in configuration The 'mode' option has not been set, webpack will fallback to 'production' for this value. Set 'mode' option to 'development' or 'production' to enable defaults for each environment. You can also set it to 'none' to disable any default behavior. Learn more: webpack.js.org/concepts/mo…

由于 webpack 在4.0后,新增mode配置项,它为我们默认设置了 production 。但是该警告并没有影响 build 的结果暂且忽略。 可以看到 dist 目录已经生成了名为 my-first-webpack.bundle.js 文件。

OK,最基本的配置已经完成,接下来引入React。

React

安装react依赖

使用

在使用前,需要在dist目录中,添加 index.html ,内容如下:

从react官网官网找段HelloWorld贴过来吧,全英文看不懂?没关系,代码你总认识吧,贴就完了!

将 index.js 中的内容变更如下:

OK,看似完美,执行下, build 看看效果。

报错了?莫慌,从错误信息中找关键字, You may need an appropriate loader to handle this file type. 。 这时候感慨一句,程序员是伟大的,错误信息很详细了,告诉我们需要适当的 loader 来处理这个文件。什么 loader?别问我,不是我干的,继续往下看刚才的链接下一小节react-jsx的介绍,拉到最下面,是不是有一段关于官方的建议?继续查找关键字,是不是看到一个叫 Babel 的东西?纳尼,莫非 jsx 和它有关系?虽然这段话是说推荐编辑器设置的吧,但是 程序员 必备一颗好奇的心。

Babel

Google一下上面的关键词 Babel ,进去瞅瞅吧。 于是开始接触一个新名词 Babel ,这玩意干啥的?能为我们带来什么?看看首页吧。

  • ES2015 及更高版本

    Babel 通过语法转换器支持最新版本的 JavaScript 。

  • Polyfill

    由于 Babel 只转换语法(如箭头函数), 你可以使用 babel-polyfill 支持新的全局变量,例如 Promise 、新的原生方法。

  • JSX 和 Flow

    Babel 能够转换 JSX 语法并去除类型注释。

  • 可插拔

    Babel 是建立在插件之外的。 你可以使用已有的插件或者自己编写插件来组成属于你自己的转换管道。

  • 可调式

    支持 Source map 因此可以轻松调试编译后代码。

看完首页的介绍,是否和我有同样的感叹:好东西啊!既然是好东西,用起来吧。 从配置的 webpack 选项中,你会发现刚才出现的两个关键字都来了 babel 、 loader ,艾玛,得来全不费工夫。

通过 config 配置

将 webpack.config.js 修改配置如下:

创建 .babelrc 配置文件

将以下内容粘贴至 .babelrc 中:

至此,已经将上面的 babel-preset-env 、 babel-preset-react 使用上了,那 polyfill 怎么用呢?继续看波文档吧。emmm,写的很清楚了,我们把 polyfill 使用上吧,修改 webpack.config.js 中的配置如下:

该配置的都配置完了,执行下 npm run build 看看效果?果不其然,编译过了。

你以为工程就这样配完了吗?NO,这仅仅是个开始!

react-router

SPA工程中使用,什么是SPA,单页应用?什么是单页应用?只有一个html,公用js css仅引用一次,通过局部刷新渲染的应用。

react-router官网,按着快速上手的步骤来。

安装

使用

这里从 create-react-app 中使用方式,虽然我们不是,但是我们自己搭的也不差啊。自己建个 src 和 App.js吧。

将官方的:chestnut:贴进来 App.js :

接下来在 index.js 中引用:

执行 npm run build 看看。没报错,使用浏览器打开 dist/index.html 看看。点击链接没反应?什么情况?莫慌,打开控制台看看:

emmmm,咋整?别问我,真不是我干的… 既然chrome不好使,就再看一眼safari下好不好用吧,一样不好使,再看一眼报错信息。

好像safari的报错更友好一些,我们可以清楚的看到,它在试图改变链接,为了安全起见,你认为这么做合理么?岂不是拿个 html 能访问计算机任何文件了?emmm,果然不合理。再看关键词:Paths and fragments must match for a sandboxed document 。

那我们就构建个沙盒环境吧。

webpack-dev-server

安装

修改配置

  • 在 package.json 中添加 scripts :
  • 在 webpack.config.js 根节点 中,添加:
  • 执行上面刚添加的 srcripts :

.container {
list-style: none;
}

js import './app.css';

<ul className="container">
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About</Link></li>
<li><Link to="/topics">Topics</Link></li>
</ul>//在此我向大家推荐一个前端全栈开发交流圈:619586920 突破技术瓶颈,提升思维能力

bash
yarn add style-loader css-loader --dev</pre>

{
test: /.css$/,
use: [
'style-loader',
'css-loader'
]
}

import styles from 'app.css';

<div className={styles.container} />

'css-loader?modules&localIdentName=[name]-[hash:base64:5]',

yarn add file-loader --dev

{ test:
/.(png|svg|jpg|gif)$/, use: [
'file-loader'
] }

{ test:
/.(woff|woff2|eot|ttf|otf)$/, use: [
'file-loader'
] }

yarn add html-webpack-plugin --dev

[ new HtmlWebpackPlugin({ title: 'Output Management' }) ],

new HtmlWebpackPlugin({ title: 'Demo', template: './index.html' })

yarn add clean-webpack-plugin --dev

const CleanWebpackPlugin = require('clean-webpack-plugin');

new CleanWebpackPlugin(['dist']),

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');

module.exports = {
entry: ["babel-polyfill", "./index.js"],
output: {
path: path.resolve(__dirname, '../dist'),
filename: '[name].[contenthash:12].js'
},
module: {
rules: [
{
test: /.js$/,
exclude: /node_modules/,
loader: "babel-loader?cacheDirectory"
},
{
test: /.css$/,
use: [
'style-loader',
"css-loader"
]
},
{
test: /.(png|svg|jpg|gif)$/,
use: [
'file-loader'
]
},
{
test: /.(woff|woff2|eot|ttf|otf)$/,
use: [
'file-loader'
]
}
]
},
plugins: [
new CleanWebpackPlugin(["dist"], {
root: path.resolve(__dirname, "../"),
}),
new HtmlWebpackPlugin({
title: 'Demo',
template: './index.html'
})
]
};

const merge = require('webpack-merge');
const common = require('./webpack.common');
const path = require('path');

module.exports = merge(common, {
mode: 'development',
devtool: 'inline-source-map',
devServer: {
contentBase: path.resolve(__dirname, '../dist'),
compress: true,
port: 9000
}//在此我向大家推荐一个前端全栈开发交流圈:619586920 突破技术瓶颈,提升思维能力
});

const merge = require('webpack-merge');
const common = require('./webpack.common');

module.exports = merge(common, {
mode: 'production',
});

"build": "webpack --config config/webpack.prod.js",
"dev": "webpack-dev-server --config config/webpack.dev.js"

yarn add extract-text-webpack-plugin --dev

const path = require('path');
const ExtractTextPlugin = require("extract-text-webpack-plugin");

module.exports = {
mode: "production",
entry: ["babel-polyfill", "./index.js"],
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'my-first-webpack.bundle.js'
},
module: {
rules: [
{
test: /.js$/,
exclude: /node_modules/,
loader: "babel-loader?cacheDirectory"
},
{
test: /.css$/,
use: ExtractTextPlugin.extract({
fallback: "style-loader",
use: "css-loader"
})
},
{
test: /.(png|svg|jpg|gif)$/,
use: [
'file-loader'
]
},
{
test: /.(woff|woff2|eot|ttf|otf)$/,
use: [
'file-loader'
]
}
]
},
plugins: [
new ExtractTextPlugin("styles.css"),
],
devServer: {
contentBase: path.join(__dirname, 'dist'),
compress: true,
port: 9000
}
};

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = {
entry: ["babel-polyfill", "./index.js"],
output: {
path: path.resolve(__dirname, '../dist'),
filename: '[name].[contenthash:12].js'
},
module: {
rules: [
{
test: /.js$/,
exclude: /node_modules/,
loader: "babel-loader?cacheDirectory"
},
{
test: /.css$/,
use: [
MiniCssExtractPlugin.loader,
'css-loader?modules&localIdentName=[name]-[hash:base64:5]',
]
},
{
test: /.(png|svg|jpg|gif)$/,
use: [
'file-loader'
]
},
{
test: /.(woff|woff2|eot|ttf|otf)$/,
use: [
'file-loader'
]
}
]
},
plugins: [
new CleanWebpackPlugin(["dist"], {
root: path.resolve(__dirname, "../"),
}),
new HtmlWebpackPlugin({
title: 'Demo',
template: './index.html'
}),
]
};

const merge = require('webpack-merge');
const common = require('./webpack.common');
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");

module.exports = merge(common, {
mode: 'production',
optimization: {
minimizer: [
new UglifyJsPlugin({
cache: true,
parallel: true,
sourceMap: true
}),
new OptimizeCSSAssetsPlugin({}) // use OptimizeCSSAssetsPlugin
]
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].[contenthash:12].css',
chunkFilename: '[name].[contenthash:12].css' // use contenthash *
})//在此我向大家推荐一个前端全栈开发交流圈:619586920 突破技术瓶颈,提升思维能力
]
});

const merge = require('webpack-merge');
const common = require('./webpack.common');
const path = require('path');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = merge(common, {
mode: 'development',
devtool: 'inline-source-map',
devServer: {
contentBase: path.resolve(__dirname, '../dist'),
compress: true,
port: 9000
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[id].css',
}),
]
});

const merge = require('webpack-merge');
const common = require('./webpack.common');
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin");

module.exports = merge(common, {
mode: 'production',
optimization: {
minimizer: [
new UglifyJsPlugin({
cache: true,
parallel: true,
sourceMap: true
}),
new OptimizeCSSAssetsPlugin({}) // use OptimizeCSSAssetsPlugin
],
runtimeChunk: {
name: "manifest"
},
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: "vendors",
priority: -20,
chunks: "all"
}//在此我向大家推荐一个前端全栈开发交流圈:619586920 突破技术瓶颈,提升思维能力
}
}
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].[contenthash:12].css',
chunkFilename: '[name].[contenthash:12].css' // use contenthash *
})
]
});

npm install eslint -g #全局安装eslint

eslint --init

? How would you like to configure ESLint? Use a popular style guide
? Which style guide do you want to follow? Airbnb (https://github.com/airbnb/javascript)
? Do you use React? Yes
? What format do you want your config file to be in? JavaScript
Checking peerDependencies of eslint-config-airbnb@latest
? The style guide "airbnb" requires eslint@^4.19.1. You are currently using eslint@5.2.0.
Do you want to downgrade? Yes

module.exports = {
"extends": "airbnb",
"plugins":[
"react",
"jsx-a11y",
"import"
],
"rules": {
"import/no-extraneous-dependencies": "off",
"react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }],
"react/prop-types": 0
}
};

yarn add antd

yarn add babel-plugin-import --dev

{
"presets": ["env", "react"],
"plugins": [
["import", { "libraryName": "antd", "libraryDirectory": "es", "style": "css" }]
]
}

import { DatePicker } from 'antd';

const Home = () => (
<div>
<h2>
<DatePicker />
</h2>
</div>
);

{
test: /.css$/,
exclude: /node_modules/,
use: [
MiniCssExtractPlugin.loader,
'css-loader?modules&localIdentName=[name]-[hash:base64:5]',
],
},
{// antd样式处理
test: /.css$/,
exclude: /src/,
use: [
{ loader: 'style-loader' },
{
loader: 'css-loader',
options: {
importLoaders: 1,
},//在此我向大家推荐一个前端全栈开发交流圈:619586920 突破技术瓶颈,提升思维能力
},
],
},

评论 ( 0 )
最新评论
暂无评论

赶紧努力消灭 0 回复