查看所有文档页面: 全栈开发 https://whjin.github.io/full-stack-development/ , 获取更多信息.
快马加鞭, 加班加点, 终于把这个文档整理出来了, 顺便深入地学习一番, 巩固知识, 就是太累人, 影响睡眠时间和质量. 极客就是想要把事情做到极致, 开始了就必须到达终点.
本章教你如何用 Webpack 去解决实际项目中常见的场景.
按照不同场景划分成以下几类:
使用新语言来开发项目:
使用 ES6 语言
使用 TypeScript 语言
使用 Flow 检查器
使用 SCSS 语言
使用 PostCSS
使用新框架来开发项目:
使用 React 框架
使用 Vue 框架
使用 Angular2 框架
用 Webpack 构建单页应用:
为单页应用生成 HTML
管理多个单页应用
用 Webpack 构建不同运行环境的项目:
构建同构应用
构建 Electron 应用
构建 Npm 模块
构建离线应用
Webpack 结合其它工具搭配使用, 各取所长:
搭配 Npm Script
检查代码
通过 Node.js API 启动 Webpack
使用 Webpack Dev Middleware
用 Webpack 加载特殊类型的资源:
加载图片
加载 SVG
加载 Source Map
使用 TypeScript 语言
由于本文不推荐使用 TypeScript,ES6 就足够完成大部分任务. 原文链接: 使用 TypeScript 语言 http://webpack.wuhaolin.cn/3实战/3-2使用TypeScript语言.html
使用 Angular2 框架
使用 ES6 语言
通常我们需要把采用 ES6 编写的代码转换成目前已经支持良好的 ES5 代码, 这包含 2 件事:
把新的 ES6 语法用 ES5 实现, 例如 ES6 的 class 语法用 ES5 的 prototype 实现.
给新的 API 注入 polyfill , 例如使用新的 fetch API 时注入对应的 polyfill 后才能让低端浏览器正常运行.
Babel
Babel 可以方便的完成以上 2 件事.
Babel 是一个 JavaScript 编译器, 能将 ES6 代码转为 ES5 代码, 让你使用最新的语言特性而不用担心兼容性问题, 并且可以通过插件机制根据需求灵活的扩展.
在 Babel 执行编译的过程中, 会从项目根目录下的 .babelrc 文件读取配置..babelrc 是一个 JSON 格式的文件, 内容大致如下:
- {
- "plugins": [
- [
- "transform-runtime",
- {"polyfill": false}
- ]
- ],
- "presets": [
- [
- "es2015",
- {
- "modules": false
- }
- ],
- "stage-2",
- "react"
- ]
- }
- Plugins
plugins 属性告诉 Babel 要使用哪些插件, 插件可以控制如何转换代码.
以上配置文件里的 transform-runtime 对应的插件全名叫做
babel-plugin-transform-runtime
, 即在前面加上了 babel-plugin-, 要让 Babel 正常运行我们必须先安装它:
- npm i -D babel-plugin-transform-runtime
- babel-plugin-transform-runtime
是 Babel 官方提供的一个插件, 作用是减少冗余代码.
Babel 在把 ES6 代码转换成 ES5 代码时通常需要一些 ES5 写的辅助函数来完成新语法的实现, 例如在转换 class extent 语法时会在转换后的 ES5 代码里注入 _extent 辅助函数用于实现继承:
- function _extent(target) {
- for (var i = 1; i <arguments.length; i++) {
- var source = arguments[i];
- for (var key in source) {
- if (Object.prototype.hasOwnProperty.call(source, key)) {
- target[key] = source[key];
- }
- }
- }
- return target;
- }
这会导致每个使用了 class extent 语法的文件都被注入重复的 _extent 辅助函数代码,
babel-plugin-transform-runtime
的作用在于不把辅助函数内容注入到文件里, 而是注入一条导入语句:
var _extent = require('babel-runtime/helpers/_extent');
- module.exports = {
- module: {
- rules: [
- {
- test: /\.js$/,
- use: ['babel-loader'],
- },
- ]
- },
- // 输出 source-map 方便直接调试 ES6 源码
- devtool: 'source-map'
- };
- # Webpack 接入 Babel 必须依赖的模块
- npm i -D babel-core babel-loader
- # 根据你的需求选择不同的 Plugins 或 Presets
- npm i -D babel-preset-env
- $blue: #1875e7;
- div {
- color: $blue;
- }
- # 把 main.scss 源文件编译成 main.css
- node-sass main.scss main.css
- module.exports = {
- module: {
- rules: [
- {
- // 增加对 SCSS 文件的支持
- test: /\.scss/,
- // SCSS 文件的处理顺序为先 sass-loader 再 css-loader 再 style-loader
- use: ['style-loader', 'css-loader', 'sass-loader'],
- },
- ]
- },
- };
- # 安装 Webpack Loader 依赖
- npm i -D sass-loader css-loader style-loader
- # sass-loader 依赖 node-sass
- npm i -D node-sass
- // @flow
- // 静态类型检查
- function square1(n: number): number {
- return n * n;
- }
- square1('2'); // Error: square1 需要传入 number 作为参数
- // 类型推断检查
- function square2(n) {
- return n * n; // Error: 传入的 string 类型不能做乘法运算
- }
- square2('2');
- "scripts": {
- "flow": "flow"
- }
- // 采用 Flow 的源代码
- function foo(one: any, two: number, three?): string {}
- // 去掉静态类型语法后输出代码
- function foo(one, two, three) {}
- "presets": [
- ...[],
- "flow"
- ]
- /* 输入 */
- h1 {
- display: flex;
- }
- /* 输出 */
- h1 {
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
- display: flex;
- }
- /* 输入 */
- :root {
- --red: #d33;
- }
- h1 {
- color: var(--red);
- }
- /* 输出 */
- h1 {
- color: #d33;
- }
- module.exports = {
- plugins: [
- // 需要使用的插件列表
- require('postcss-cssnext')
- ]
- }
- module.exports = {
- module: {
- rules: [
- {
- // 使用 PostCSS 处理 CSS 文件
- test: /\.css/,
- use: ['style-loader', 'css-loader', 'postcss-loader'],
- },
- ]
- },
- };
- # 安装 Webpack Loader 依赖
- npm i -D postcss-loader css-loader style-loader
- # 根据你使用的特性安装对应的 PostCSS 插件依赖
- npm i -D postcss-cssnext
- class Button extends Component {
- render() {
- return <h1>Hello,Webpack</h1>
- }
- }
- // 原 JSX 语法代码
- return <h1>Hello,Webpack</h1>
- // 被转换成正常的 JavaScript 代码
- return React.createElement('h1', null, 'Hello,Webpack')
- # 安装 React 基础依赖
- npm i -D react react-dom
- # 安装 babel 完成语法转换所需依赖
- npm i -D babel-preset-react
- "presets": [
- "react"
- ],
- import * as React from 'react';
- import { Component } from 'react';
- import { render } from 'react-dom';
- class Button extends Component {
- render() {
- return <h1>Hello,Webpack</h1>
- }
- }
- render(<Button/>, window.document.getElementById('app'));
- {
- "compilerOptions": {
- "jsx": "react" // 开启 jsx , 支持 React
- }
- }
- module.exports = {
- // TS 执行入口文件
- entry: './main',
- output: {
- filename: 'bundle.js',
- path: path.resolve(__dirname, './dist'),
- },
- resolve: {
- // 先尝试 ts,tsx 后缀的 TypeScript 源码文件
- extensions: ['.ts', '.tsx', '.js',]
- },
- module: {
- rules: [
- {
- // 同时匹配 ts,tsx 后缀的 TypeScript 源码文件
- test: /\.tsx?$/,
- loader: 'awesome-typescript-loader'
- }
- ]
- },
- devtool: 'source-map',// 输出 Source Map 方便在浏览器里调试 TypeScript 代码
- };
- import Vue from 'vue'
- import App from './App.vue'
- new Vue({
- el: '#app',
- render: h => h(App)
- });
- module: {
- rules: [
- {
- test: /\.vue$/,
- use: ['vue-loader'],
- },
- ]
- }
- # Vue 框架运行需要的库
- npm i -S vue
- # 构建所需的依赖
- npm i -D vue-loader css-loader vue-template-compiler
- {
- "compilerOptions": {
- // 构建出 ES5 版本的 JavaScript, 与 Vue 的浏览器支持保持一致
- "target": "es5",
- // 开启严格模式, 这可以对 `this` 上的数据属性进行更严格的推断
- "strict": true,
- // TypeScript 编译器输出的 JavaScript 采用 es2015 模块化, 使 Tree Shaking 生效
- "module": "es2015",
- "moduleResolution": "node"
- }
- }
- <!-- 组件逻辑 -->
- <script lang="ts">
- import Vue from "vue";
- // 通过 Vue.extend 启用 TypeScript 类型推断
- export default Vue.extend({
- data() {
- return {
- msg: 'Hello,Webpack',
- }
- },
- });
- </script>
- import Vue from 'vue'
- import App from './App.vue'
- new Vue({
- el: '#app',
- render: h => h(App)
- });
- // 告诉 TypeScript 编译器 .vue 文件其实是一个 Vue
- declare module "*.vue" {
- import Vue from "vue";
- export default Vue;
- }
- const path = require('path');
- module.exports = {
- resolve: {
- // 增加对 TypeScript 的 .ts 和 .vue 文件的支持
- extensions: ['.ts', '.js', '.vue', '.json'],
- },
- module: {
- rules: [
- // 加载 .ts 文件
- {
- test: /\.ts$/,
- loader: 'ts-loader',
- exclude: /node_modules/,
- options: {
- // 让 tsc 把 vue 文件当成一个 TypeScript 模块去处理, 以解决 moudle not found 的问题, tsc 本身不会处理 .vue 结尾的文件
- appendTsSuffixTo: [/\.vue$/],
- }
- },
- ]
- },
- };
- new WebPlugin({
- template: './template.html', // HTML 模版文件所在的文件路径
- filename: 'index.html' // 输出的 HTML 的文件名称
- })
- <head>
- <meta charset="UTF-8">
- <!-- 注入 Chunk app 中的 CSS-->
- <link rel="stylesheet" href="app?_inline">
- <!-- 注入 google_analytics 中的 JavaScript 代码 -->
- <script src="./google_analytics.js?_inline"></script>
- <!-- 异步加载 Disqus 评论 -->
- <script src="https://dive-into-webpack.disqus.com/embed.js" async></script>
- </head>
- <body>
- <div id="app"></div>
- <!-- 导入 Chunk app 中的 JS-->
- <script src="app"></script>
- <!--Disqus 评论容器 -->
- <div id="disqus_thread"></div>
- </body>
- <p data-height="565" data-theme-id="0" data-slug-hash="mLYOeK" data-default-tab="html,result" data-user="whjin" data-embed-version="2" data-pen-title="管理多个单页应用" class="codepen">See the Pen 管理多个单页应用 https://codepen.io/whjin/pen/mLYOeK/ by whjin (@whjin https://codepen.io/whjin ) on CodePen https://codepen.io/ .</p>
- <script async src="https://static.codepen.io/assets/embed/ei.js" ;></script>
- dist
- common_029086ff.js
- common_7cc98ad0.css
- index.html
- index_04c08fbf.css
- index_b3d3761c.js
- login.html
- login_0a3feca9.js
- login_e31e214b.css
- new WebPlugin({
- template: './template.html', // HTML 模版文件所在的文件路径
- filename: 'login.html' // 输出的 HTML 的文件名称
- })
- entry: {
- index: './pages/index/index.js',// 页面 index.html 的入口文件
- login: './pages/login/index.js',// 页面 login.html 的入口文件
- }
- pages
- index
- index.css // 该页面单独需要的 CSS 样式
- index.js // 该页面的入口文件
- login
- index.css
- index.js
- common.css // 所有页面都需要的公共 CSS 样式
- google_analytics.js
- template.html
- webpack.config.js
- <p data-height="465" data-theme-id="0" data-slug-hash="gzJWwB" data-default-tab="js,result" data-user="whjin" data-embed-version="2" data-pen-title="webpack 管理多个单页应用" class="codepen">See the Pen webpack 管理多个单页应用 https://codepen.io/whjin/pen/gzJWwB/ by whjin (@whjin https://codepen.io/whjin ) on CodePen https://codepen.io/ .</p>
- <script async src="https://static.codepen.io/assets/embed/ei.js" ;></script>
- {
- "index":["./pages/index/index.js","./common.css"],
- "login":["./pages/login/index.js","./common.css"]
- }
- <html>
- <head>
- <meta charset="UTF-8">
- <!-- 在这注入该页面所依赖但没有手动导入的 CSS-->
- <!--STYLE-->
- <!-- 注入 google_analytics 中的 JS 代码 -->
- <script src="./google_analytics.js?_inline"></script>
- <!-- 异步加载 Disqus 评论 -->
- <script src="https://dive-into-webpack.disqus.com/embed.js" async></script>
- </head>
- <body>
- <div id="app"></div>
- <!-- 在这注入该页面所依赖但没有手动导入的 JavaScript-->
- <!--SCRIPT-->
- <!--Disqus 评论容器 -->
- <div id="disqus_thread"></div>
- </body>
- </html>
- <p data-height="580" data-theme-id="0" data-slug-hash="WJBEza" data-default-tab="js,result" data-user="whjin" data-embed-version="2" data-pen-title="webpack_server.config.js" class="codepen">See the Pen webpack_server.config.js https://codepen.io/whjin/pen/WJBEza/ by whjin (@whjin https://codepen.io/whjin ) on CodePen https://codepen.io/ .</p>
- <script async src="https://static.codepen.io/assets/embed/ei.js" ;></script>
- externals: [nodeExternals()]
- webpack-node-externals
- import React, { Component } from 'react';
- import './main.css';
- export class AppComponent extends Component {
- render() {
- return <h1>Hello,Webpack</h1>
- }
- }
- import React from 'react';
- import { render } from 'react-dom';
- import { AppComponent } from './AppComponent';
- // 把根组件渲染到 DOM 树上
- render(<AppComponent/>, window.document.getElementById('app'));
- const express = require('express');
- const { render } = require('./dist/bundle_server');
- const app = express();
- // 调用构建出的 bundle_server.js 中暴露出的渲染函数, 再拼接下 HTML 模版, 形成完整的 HTML 文件
- app.get('/', function (req, res) {
- res.send(`
- <html>
- <head>
- <meta charset="UTF-8">
- </head>
- <body>
- <div id="app">${render()}</div>
- <!-- 导入 Webpack 输出的用于浏览器端渲染的 JS 文件 -->
- <script src="./dist/bundle_browser.js"></script>
- </body>
- </html>
- `);
- });
- // 其它请求路径返回对应的本地文件
- app.use(express.static('.'));
- app.listen(3000, function () {
- console.log('app listening on port 3000!')
- });
- # 安装 Webpack 构建依赖
- npm i -D css-loader style-loader ignore-loader webpack-node-externals
- # 安装 HTTP 服务器依赖
- npm i -S express
- <p data-height="565" data-theme-id="0" data-slug-hash="vjweQv" data-default-tab="js" data-user="whjin" data-embed-version="2" data-pen-title="Electron-main.js" class="codepen">See the Pen Electron-main.js https://codepen.io/whjin/pen/vjweQv/ by whjin (@whjin https://codepen.io/whjin ) on CodePen https://codepen.io/ .</p>
- <script async src="https://static.codepen.io/assets/embed/ei.js" ;></script>
- <p data-height="665" data-theme-id="0" data-slug-hash="odRogQ" data-default-tab="js" data-user="whjin" data-embed-version="2" data-pen-title="main.js" class="codepen">See the Pen main.js https://codepen.io/whjin/pen/odRogQ/ by whjin (@whjin https://codepen.io/whjin ) on CodePen https://codepen.io/ .</p>
- <script async src="https://static.codepen.io/assets/embed/ei.js" ;></script>
- # 安装 Electron 执行环境到项目中
- npm i -D electron
- node_modules/hello-webpack
- lib
- index.css (组件所有依赖的 CSS 都在这个文件中)
- index.css.map
- index.js (符合 CommonJS 模块化规范的 ES5 代码)
- index.js.map
- src (ES6 源码)
- index.css
- index.js
- package.json (模块描述文件)
- import React, { Component } from 'react';
- import './index.css';
- // 导出该组件供给其它模块使用
- export default class HelloWebpack extends Component {
- render() {
- return <h1 className="hello-component">Hello,Webpack</h1>
- }
- }
- // 通过 ES6 语法导入
- import HelloWebpack from 'hello-webpack';
- import 'hello-webpack/lib/index.css';
- // 或者通过 ES5 语法导入
- var HelloWebpack = require('hello-webpack');
- require('hello-webpack/lib/index.css');
- // 使用 react-dom 渲染
- render(<HelloWebpack/>);
- module.exports = {
- output: {
- // 输出的代码符合 CommonJS 模块化规范, 以供给其它模块导入使用.
- libraryTarget: 'commonjs2',
- },
- // 输出 Source Map
- devtool: 'source-map',
- };
- const ExtractTextPlugin = require('extract-text-webpack-plugin');
- module.exports = {
- module: {
- rules: [
- {
- // 增加对 CSS 文件的支持
- test: /\.css/,
- // 提取出 Chunk 中的 CSS 代码到单独的文件中
- use: ExtractTextPlugin.extract({
- use: ['css-loader']
- }),
- },
- ]
- },
- plugins: [
- new ExtractTextPlugin({
- // 输出的 CSS 文件名称
- filename: 'index.css',
- }),
- ],
- };
- # 安装 Webpack 构建所需要的新依赖
- npm i -D style-loader css-loader extract-text-webpack-plugin
- class HelloWebpack extends Component{
- }
- {
- "plugins": [
- [
- "transform-runtime",
- {
- // transform-runtime 默认会自动的为你使用的 ES6 API 注入 polyfill
- // 假如你在源码中使用了 Promise, 输出的代码将会自动注入 require('babel-runtime/core-js/Promise') 语句
- // polyfill 的注入应该交给模块使用者, 因为使用者可能在其它地方已经注入了其它的 Promise polyfill 库
- // 所以关闭该功能
- "polyfill": false
- }
- ]
- ]
- }
- # 安装 Webpack 构建所需要的新依赖
- npm i -D babel-plugin-transform-runtime
- # 安装输出代码运行时所需的新依赖
- npm i -S babel-runtime
- module.exports = {
- // 通过正则命中所有以 react 或者 babel-runtime 开头的模块
- // 这些模块通过注册在运行环境中的全局变量访问, 不用被重复打包进输出的代码里
- externals: /^(react|babel-runtime)/,
- };
- [
- (function (module, exports) {
- module.exports = require("babel-runtime/helpers/inherits");
- }),
- (function (module, exports) {
- module.exports = require("react");
- })
- ]
- <p data-height="565" data-theme-id="0" data-slug-hash="gzJdam" data-default-tab="js" data-user="whjin" data-embed-version="2" data-pen-title="构建 Npm 模块" class="codepen">See the Pen 构建 Npm 模块 https://codepen.io/whjin/pen/gzJdam/ by whjin (@whjin https://codepen.io/whjin ) on CodePen https://codepen.io/ .</p>
- <script async src="https://static.codepen.io/assets/embed/ei.js" ;></script>
- {
- "main": "lib/index.js",
- "jsnext:main": "src/index.js"
- }
- // 如果 navigator 对象上存在 serviceWorker 对象, 就表示支持
- if (navigator.serviceWorker) {
- // 通过 navigator.serviceWorker 使用
- }
- if (navigator.serviceWorker) {
- window.addEventListener('DOMContentLoaded',function() {
- // 调用 serviceWorker.register 注册, 参数 /sw.js 为脚本文件所在的 URL 路径
- navigator.serviceWorker.register('/sw.js');
- });
- }
- // 当前缓存版本的唯一标识符, 用当前时间代替
- var cacheKey = new Date().toISOString();
- // 需要被缓存的文件的 URL 列表
- var cacheFileList = [
- '/index.html',
- '/app.js',
- '/app.css'
- ];
- // 监听 install 事件
- self.addEventListener('install', function (event) {
- // 等待所有资源缓存完成时, 才可以进行下一步
- event.waitUntil(
- caches.open(cacheKey).then(function (cache) {
- // 要缓存的文件 URL 列表
- return cache.addAll(cacheFileList);
- })
- );
- });
- self.addEventListener('fetch', function(event) {
- event.respondWith(
- // 去缓存中查询对应的请求
- caches.match(event.request).then(function(response) {
- // 如果命中本地缓存, 就直接返回本地的资源
- if (response) {
- return response;
- }
- // 否则就去用 fetch 下载资源
- return fetch(event.request);
- }
- )
- );
- });
- // 当前缓存白名单, 在新脚本的 install 事件里将使用白名单里的 key
- var cacheWhitelist = [cacheKey];
- self.addEventListener('activate', function(event) {
- event.waitUntil(
- caches.keys().then(function(cacheNames) {
- return Promise.all(
- cacheNames.map(function(cacheName) {
- // 不在白名单的缓存全部清理掉
- if (cacheWhitelist.indexOf(cacheName) === -1) {
- // 删除缓存
- return caches.delete(cacheName);
- }
- })
- );
- })
- );
- });
- <p data-height="565" data-theme-id="0" data-slug-hash="gzJZKX" data-default-tab="js" data-user="whjin" data-embed-version="2" data-pen-title="Service Workers" class="codepen">See the Pen Service Workers https://codepen.io/whjin/pen/gzJZKX/ by whjin (@whjin https://codepen.io/whjin ) on CodePen https://codepen.io/ .</p>
- <script async src="https://static.codepen.io/assets/embed/ei.js" ;></script>
- app_4c3e186f.js
- app_7cc98ad0.css
- index.html
- var cacheFileList = [
- '/index.html',
- 'app_4c3e186f.js',
- 'app_7cc98ad0.css'
- ];
- <p data-height="565" data-theme-id="0" data-slug-hash="WJBLga" data-default-tab="js" data-user="whjin" data-embed-version="2" data-pen-title="serviceworker-webpack-plugin" class="codepen">See the Pen serviceworker-webpack-plugin https://codepen.io/whjin/pen/WJBLga/ by whjin (@whjin https://codepen.io/whjin ) on CodePen https://codepen.io/ .</p>
- <script async src="https://static.codepen.io/assets/embed/ei.js" ;></script>
- // 需要被缓存的文件的 URL 列表
- var cacheFileList = global.serviceWorkerOption.assets;
- {
- "scripts": {
- "dev": "node dev.js",
- "pub": "node build.js"
- }
- }
- {
- "scripts": {
- "build": "webpack"
- }
- }
- "scripts": {
- "dev": "webpack-dev-server --open",
- "dist": "NODE_ENV=production webpack --config webpack_dist.config.js",
- "pub": "npm run dist && rsync dist"
- },
- {
- // 从 eslint:recommended 中继承所有检查规则
- "extends": "eslint:recommended",
- // 再自定义一些规则
- "rules": {
- // 需要在每行结尾加 ;
- "semi": ["error", "always"],
- // 需要使用 ""包裹字符串"quotes": ["error","double"]
- }
- }
- {
- // 继承 stylelint-config-standard 中的所有检查规则
- "extends": "stylelint-config-standard",
- // 再自定义检查规则
- "rules": {
- "at-rule-empty-line-before": null
- }
- }
- module.exports = {
- module: {
- rules: [
- {
- test: /\.js$/,
- // node_modules 目录的下的代码不用检查
- exclude: /node_modules/,
- loader: 'eslint-loader',
- // 把 eslint-loader 的执行顺序放到最前面, 防止其它 Loader 把处理后的代码交给 eslint-loader 去检查
- enforce: 'pre',
- },
- ],
- },
- }
- module.exports = {
- module: {
- rules: [
- {
- test: /\.js$/,
- // node_modules 目录的下的代码不用检查
- exclude: /node_modules/,
- loader: 'tslint-loader',
- // 把 tslint-loader 的执行顺序放到最前面, 防止其它 Loader 把处理后的代码交给 tslint-loader 去检查
- enforce: 'pre',
- },
- ],
- },
- }
- const StyleLintPlugin = require('stylelint-webpack-plugin');
- module.exports = {
- // ...
- plugins: [
- new StyleLintPlugin(),
- ],
- }
- {
- "scripts": {
- // 在执行 git commit 前会执行的脚本
- "precommit": "npm run lint",
- // 在执行 git push 前会执行的脚本
- "prepush": "lint",
- // 调用 eslint,stylelint 等工具检查代码
- "lint": "eslint && stylelint"
- }
- }
- node ./node_modules/webpack/bin/webpack.js
- .
- const webpack = require('webpack');
- // ES6 语法
- import webpack from "webpack";
- webpack({
- // Webpack 配置, 和 webpack.config.js 文件一致
- }, (err, stats) => {
- if (err || stats.hasErrors()) {
- // 构建过程出错
- }
- // 成功执行完构建
- });
- // 读取 webpack.config.js 文件中的配置
- const config = require('./webpack.config.js');
- webpack(config , callback);
- <p data-height="340" data-theme-id="0" data-slug-hash="VxJwoY" data-default-tab="js" data-user="whjin" data-embed-version="2" data-pen-title="Compiler" class="codepen">See the Pen Compiler https://codepen.io/whjin/pen/VxJwoY/ by whjin (@whjin https://codepen.io/whjin ) on CodePen https://codepen.io/ .</p>
- <script async src="https://static.codepen.io/assets/embed/ei.js" ;></script>
- <p data-height="345" data-theme-id="0" data-slug-hash="erwmZQ" data-default-tab="js" data-user="whjin" data-embed-version="2" data-pen-title="webpack-dev-middleware" class="codepen">See the Pen webpack-dev-middleware https://codepen.io/whjin/pen/erwmZQ/ by whjin (@whjin https://codepen.io/whjin ) on CodePen https://codepen.io/ .</p>
- <script async src="https://static.codepen.io/assets/embed/ei.js" ;></script>
- <p data-height="500" data-theme-id="0" data-slug-hash="NMZPbX" data-default-tab="js" data-user="whjin" data-embed-version="2" data-pen-title="Webpack Dev Middleware" class="codepen">See the Pen Webpack Dev Middleware https://codepen.io/whjin/pen/NMZPbX/ by whjin (@whjin https://codepen.io/whjin ) on CodePen https://codepen.io/ .</p>
- <script async src="https://static.codepen.io/assets/embed/ei.js" ;></script>
- <p data-height="385" data-theme-id="0" data-slug-hash="XqLJMQ" data-default-tab="js" data-user="whjin" data-embed-version="2" data-pen-title="HotModuleReplacementPlugin" class="codepen">See the Pen HotModuleReplacementPlugin https://codepen.io/whjin/pen/XqLJMQ/ by whjin (@whjin https://codepen.io/whjin ) on CodePen https://codepen.io/ .</p>
- <script async src="https://static.codepen.io/assets/embed/ei.js" ;></script>
- <p data-height="450" data-theme-id="0" data-slug-hash="yjdyvG" data-default-tab="js" data-user="whjin" data-embed-version="2" data-pen-title="server.js" class="codepen">See the Pen server.js https://codepen.io/whjin/pen/yjdyvG/ by whjin (@whjin https://codepen.io/whjin ) on CodePen https://codepen.io/ .</p>
- <script async src="https://static.codepen.io/assets/embed/ei.js" ;></script>
- if (module.hot) {
- module.hot.accept();
- }
- #app {
- background-image: url(./imgs/a.png);
- }
- #app {
- background-image: url(5556e1251a78c5afda9ee7dd06ad109b.png);
- }
- import imgB from './imgs/b.png';
- window.document.getElementById('app').innerHTML = `
- <img src="${imgB}"/>
- `;
- module.exports = {
- module: {
- rules: [
- {
- test: /\.png$/,
- use: ['file-loader']
- }
- ]
- }
- };
- #app {
- background-image: url(./imgs/a.png);
- }
- #app {
- background-image: url(data:image/png;base64,iVBORw01afer...); /* 结尾省略了剩下的 base64 编码后的数据 */
- }
- module.exports = {
- module: {
- rules: [
- {
- test: /\.png$/,
- use: [{
- loader: 'url-loader',
- options: {
- // 30KB 以下的文件采用 url-loader
- limit: 1024 * 30,
- // 否则采用 file-loader, 默认值就是 file-loader
- fallback: 'file-loader',
- }
- }]
- }
- ]
- },
- };
- body {
- background-image: url(./svgs/activity.svg);
- }
- module.exports = {
- module: {
- rules: [
- {
- test: /\.svg/,
- use: ['file-loader']
- }
- ]
- },
- };
- module.exports = {
- module: {
- rules: [
- {
- test: /\.svg$/,
- use: ['raw-loader']
- }
- ]
- }
- };
- module.exports = {
- module: {
- rules: [
- {
- test: /\.svg$/,
- use: ['svg-inline-loader']
- }
- ]
- }
- };
- module.exports = {
- module: {
- rules: [
- {
- test: /\.js$/,
- // 只加载你关心的目录下的 Source Map, 以提升构建速度
- include: [path.resolve(root, 'node_modules/some-components/')],
- use: ['source-map-loader'],
- // 要把 source-map-loader 的执行顺序放到最前面, 如果在 source-map-loader 之前有 Loader 转换了该 JavaScript 文件, 会导致 Source Map 映射错误
- enforce: 'pre'
- }
- ]
- }
- };
来源: https://segmentfault.com/a/1190000015020658