在现有的 PHP 和 JS 项目中使用 webpack
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/43436754/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using webpack with an existing PHP and JS project
提问by KAD
I have an existing PHP project with jquery and bootstrap, not using any front-end framework.
我有一个带有 jquery 和 bootstrap 的现有 PHP 项目,没有使用任何前端框架。
I am trying to use webpack module bundler in order to create a single entry point for my project resources, manage js dependencies with node js package manager, run tasks as minify js css, image re-size...etc. And improve the browser loading time required to load a single page.
我正在尝试使用 webpack 模块打包器来为我的项目资源创建一个单一的入口点,使用 node js 包管理器管理 js 依赖项,将任务作为 minify js css 运行,图像重新调整大小...等。并改善加载单个页面所需的浏览器加载时间。
I came across the webpack tutorials and got to install it and install its dev-server, but the problem is that I am not able to understand how I will convert all my current js scripts and css links in the project (where I have a lot of jquery and CSS libraries used to provide multiple features in the project) to use webpack.
我遇到了 webpack 教程并必须安装它并安装它的开发服务器,但问题是我无法理解我将如何转换项目中所有当前的 js 脚本和 css 链接(我有很多用于在项目中提供多个功能的 jquery 和 CSS 库)以使用 webpack。
Do I have to rewrite all my JS and CSS files in a way that suits webpack? How do I make a successful migration?
我是否必须以适合 webpack 的方式重写我所有的 JS 和 CSS 文件?如何成功迁移?
Besides, I am not able to run my current php application on the webpack dev-server, is it meant to run there in the first place? It is only listing the directories of the project in the meantime.
此外,我无法在 webpack 开发服务器上运行我当前的 php 应用程序,它是否意味着首先要在那里运行?同时它只列出项目的目录。
I have created a test index.js
file and used the following webpack configuration:
我创建了一个测试index.js
文件并使用了以下 webpack 配置:
var path = require('path');
var webpack = require('webpack');
module.exports =
{
entry: [
'./public/js/index.js',
'webpack/hot/dev-server',
'webpack-dev-server/client?http://localhost:8080'
],
plugins: [
new webpack.HotModuleReplacementPlugin()
],
output: {
path: path.join(__dirname, "public/dist/js"),
publicPath : "http://localhost:8080/my_proj/public/dist/js",
filename: "bundle.js"
}
};
I added the bundle.js
to my script loads just for testing as follows hoping that the application will run on the webpack dev-server:
我添加bundle.js
到我的脚本加载只是为了测试如下希望应用程序将在 webpack 开发服务器上运行:
<script type="text/javascript" src="public/dist/js/bundle.js"></script>
<script type="text/javascript" src="public/js/jquery.min.js"></script>
<script type="text/javascript" src="public/js/jquery.migrate.js"></script>
<script type="text/javascript" src="public/js/jquery.bxslider.min.js"></script>
<script type="text/javascript" src="public/js/jquery.appear.js"></script>
<script type="text/javascript" src="public/js/jquery.countTo.js"></script>
<script type="text/javascript" src="public/js/bootstrap.js"></script>
Please help me understand the concept here and how can I make this migration successfully?
请帮助我理解这里的概念以及如何成功进行此迁移?
回答by Loilo
First, to answer your smaller questions:
首先,回答你的小问题:
- No, you're not supposed to run your PHP application through a webpack dev server. Explained in the Live Reloadingsection below.
- No, you won't have to rewrite your assets. Probably. See the CSSand Edge Casessections below.
- 不,你不应该通过 webpack 开发服务器运行你的 PHP 应用程序。在下面的实时重新加载部分中进行了解释。
- 不,您不必重写您的资产。大概。请参阅下面的CSS和Edge Cases部分。
Disclaimer:I'll only take on a small fraction of your question. Its scope is just way too broad to be packed into just one StackOverflow answer.
免责声明:我只会回答你问题的一小部分。它的范围实在是太广泛了,不能只包含在一个 StackOverflow 答案中。
I will only get in touch with
我只会联系
- setting up a development and a production environment for webpack
- bundling your first JavaScript
- 为 webpack 设置开发和生产环境
- 捆绑你的第一个 JavaScript
which should give you a foundation to build on.
这应该给你一个基础。
I'll also mention some things you may want to add and link according resources to read through.
我还将提及您可能想要添加的一些内容,并根据资源进行链接以通读。
So, let's go.
所以,我们走吧。
Requirements
要求
I assume you have Node.js and npm installed on your machine and roughly know how to use them.
我假设你已经在你的机器上安装了 Node.js 和 npm,并且大致知道如何使用它们。
I also assume you have webpack
and webpack-cli
installed as (dev) dependencies of your project (not just globally):
我还假设您已经webpack
并webpack-cli
安装为项目的(开发)依赖项(不仅仅是全局):
npm install --save-dev webpack webpack-cli
Update:Earlier versions of this answer did not require installing
webpack-cli
. As of version 4 (February 2018), webpack's CLI resides in its own package, hence the additional required package.
更新:此答案的早期版本不需要安装
webpack-cli
. 从版本 4(2018 年 2 月)开始,webpack 的 CLI 驻留在它自己的包中,因此需要额外的包。
Set up development and a production workflow
设置开发和生产工作流程
You usually want to do stuff differently in development than in production (minifying in production, live-reloading in development, ...)
您通常希望在开发和生产中做不同的事情(在生产中缩小,在开发中实时重新加载,......)
To achieve that, we'll want to split up our configuration files.
为了实现这一点,我们需要拆分我们的配置文件。
Prepare the directory structure
准备目录结构
Let's agree to ignore the webpack config from your question. We'll start all over, we'd have to change almost everything anyway.
让我们同意忽略您问题中的 webpack 配置。我们将重新开始,无论如何我们几乎必须改变一切。
First, create a build
folder inside your project root. Build-related stuff will go there, since we don't want to pollute your project's root folder with config files. (You're free to name this folder differently, but keep track of that during this tutorial.)
首先,build
在项目根目录中创建一个文件夹。构建相关的东西会放在那里,因为我们不想用配置文件污染项目的根文件夹。(您可以随意命名此文件夹,但请在本教程中对其进行跟踪。)
Create a config.base.js
, a config.production.js
and a config.development.js
file inside that folder.
在该文件夹中创建一个config.base.js
, aconfig.production.js
和一个config.development.js
文件。
Great, we have config files for two build chains now. The configurations are still empty though, so let's now fill them with some basic logic.
太好了,我们现在有两个构建链的配置文件。配置仍然是空的,所以现在让我们用一些基本逻辑来填充它们。
Install webpack-merge
安装 webpack-merge
But first, we'll need to install webpack-merge
.
但首先,我们需要安装webpack-merge
.
npm install --save-dev webpack-merge
This package allows us to deeply merge multiple webpack configurations. We want to use it to create webpack configurations depending on our current environment.
这个包允许我们深度合并多个 webpack 配置。我们想用它来根据我们当前的环境创建 webpack 配置。
Adjust your configuration
调整您的配置
Now adjust your build/config.base.js
:
现在调整你的build/config.base.js
:
module.exports = {
// We'll place webpack configuration for all environments here
}
The file does obviously just export an empty object right now, but we'll need that for the following steps.
该文件现在显然只是导出一个空对象,但我们将在以下步骤中需要它。
Put this code in your build/config.production.js
:
将此代码放入您的build/config.production.js
:
const merge = require('webpack-merge')
module.exports = merge(require('./config.base.js'), {
mode: 'production'
// We'll place webpack configuration for production environment here
})
And almost the same code goes into your build/config.development.js
:
几乎相同的代码进入您的build/config.development.js
:
const merge = require('webpack-merge')
module.exports = merge(require('./config.base.js'), {
mode: 'development',
watch: true
// All webpack configuration for development environment will go here
})
I guess it's pretty intuitive what this does:
我想这是非常直观的:
Using webpack with the config.development.js
configuration will fetch the common configuration and merge its own config declaration in.
使用带有config.development.js
配置的webpack将获取公共配置并将其自己的配置声明合并到其中。
Update:The
mode
option in the above config files was added in webpack 4 (released February 2018). It sets a bunch of sensible defaultsfor development and production bundles.
更新:
mode
上述配置文件中的选项是在 webpack 4(2018 年 2 月发布)中添加的。它为开发和生产包设置了一系列合理的默认值。
Now running the process would look like this from the command line:
现在从命令行运行该过程将如下所示:
npx webpack --config build/config.development.js
# If the above doesn't work, you probably have an older version of npm (< 5.1) installed
# While npx is a really great tool, you can of course still call the path of the webpack executable manually:
node_modules/.bin/webpack --config build/config.development.js
...and vice versa for the production
environment.
...对production
环境而言,反之亦然。
That command is rather clunky to use, but no worries, we'll address that later.
该命令使用起来相当笨拙,但不用担心,我们稍后会解决这个问题。
Make some helper files
制作一些帮助文件
There are information we'll be wanting to centralize to make them easily exchangeable. File paths are such a thing. So let's extract them.
我们希望将某些信息集中起来,以使其易于交换。文件路径就是这样。所以让我们提取它们。
Create a paths.js
in your build
folder and have it export some paths we'll want to use later:
paths.js
在您的build
文件夹中创建一个并让它导出一些我们稍后要使用的路径:
const path = require('path')
// I'm really just guessing your project's folder structure from reading your question,
// you might want to adjust this whole section
module.exports = {
// The base path of your source files, especially of your index.js
SRC: path.resolve(__dirname, '..', 'public'),
// The path to put the generated bundle(s)
DIST: path.resolve(__dirname, '..', 'public', 'dist'),
/*
This is your public path.
If you're running your app at http://example.com and I got your DIST folder right,
it'll simply be "/dist".
But if you're running it locally at http://localhost/my/app, it will be "/my/app/dist".
That means you should probably *not* hardcode that path here but write it to a
machine-related config file. (If you don't already have something like that,
google for "dotenv" or something similar.)
*/
ASSETS: '/dist'
}
Create aliases
创建别名
As mentioned above, we could technically run our build chain in development
mode like this:
如上所述,我们可以在技术上以这样的development
模式运行我们的构建链:
npx webpack --config build/config.development.js
That's an uncomfortably verbose command though, so let's change that.
虽然这是一个令人不舒服的冗长命令,所以让我们改变它。
It's way more convenient to run your build process via npm
scripts. Add one script per environment to your package.json
like this:
通过npm
脚本运行构建过程更方便。为每个环境添加一个脚本,package.json
如下所示:
{
"scripts": {
"dev": "webpack --config build/config.development.js",
"prod": "webpack --config build/config.production.js"
}
}
Now you can run your build chains with npm run dev
resp. npm run prod
– which is much easier to memorize and faster to type.
现在您可以使用npm run dev
resp运行您的构建链。npm run prod
– 这更容易记忆和更快地打字。
...as soon as there'es anything to build, of course.
...当然,只要有任何东西要建造。
Bundle JavaScript
捆绑 JavaScript
Okay, that was actually a fair amount of work without achieving too much so far.
好吧,这实际上是相当多的工作,到目前为止还没有取得太多成果。
So let's start with something more exciting: We'll define a JavaScript entry point.
因此,让我们从更令人兴奋的事情开始:我们将定义一个 JavaScript 入口点。
Define an entry point
定义入口点
Put the following code into your build/config.base.js
(replacing the existing code entirely):
将以下代码放入您的build/config.base.js
(完全替换现有代码)中:
const path = require('path')
const { SRC, DIST, ASSETS } = require('./paths')
module.exports = {
entry: {
scripts: path.resolve(SRC, 'js', 'index.js')
},
output: {
// Put all the bundled stuff in your dist folder
path: DIST,
// Our single entry point from above will be named "scripts.js"
filename: '[name].js',
// The output path as seen from the domain we're visiting in the browser
publicPath: ASSETS
}
}
Create the JavaScript file
创建 JavaScript 文件
The above configuration expects an index.js
to live in your SRC/js
folder (as defined in the build/paths.js
).
上面的配置期望 存在index.js
于您的SRC/js
文件夹中(如 中所定义build/paths.js
)。
Let's create that file with the following content:
让我们使用以下内容创建该文件:
import './jquery.min.js'
import './jquery.migrate.js'
import './jquery.bxslider.min.js'
import './jquery.appear.js'
import './jquery.countTo.js'
import './bootstrap.js'
As you can see, the index.js
just imports all of the files you want to use.
如您所见,index.js
只需导入您要使用的所有文件。
If you now run
如果你现在跑
npm run prod
from your terminal, a scripts.js
file will be created in your DIST
folder. You can include that into your markup with a plain ol' <script>
tag.
从您的终端,scripts.js
将在您的DIST
文件夹中创建一个文件。您可以使用普通的 ol'<script>
标签将其包含在您的标记中。
Congratulations, you've got a working webpack setup!
恭喜,你已经有了一个有效的 webpack 设置!
Dive deeper
潜得更深
This mini-tutorial really just scraped the surface of what you can do with webpack. It gives you a pretty solid foundation for your configuration which you now can fill with whatever you need. And that will actually be quite a lot of stuff.
这个迷你教程只是简单地介绍了 webpack 可以做的事情。它为您的配置提供了一个非常坚实的基础,您现在可以填充您需要的任何内容。这实际上将是相当多的东西。
I'll list a few more things you may want to enhance, with some links to read through.
我将列出您可能想要增强的更多内容,并提供一些链接以供阅读。
webpack Concepts
webpack 概念
If you want to use webpack, it can be hard to do so if you don't know about its underlying concepts. Juho Veps?l?inencreated a great guide on getting started with webpack which helped me a whole lot. He's also a webpack core contributor so you can be sure he knows what he's talking about.
如果你想使用 webpack,如果你不了解它的底层概念,可能很难做到。Juho Veps?l?inen创建了一个很好的webpack入门指南,对我帮助很大。他还是 webpack 的核心贡献者,所以你可以确定他知道他在说什么。
Especially loadersare a concept you'll really needto know.
尤其是装载机是您真正需要了解的概念。
Many of the hints on this list are also explained there.
此列表中的许多提示也在那里进行了解释。
Read more: SurviveJS – webpack tutorial
Code Splitting
代码拆分
It does what the name's saying: You might not want to pack all your JavaScript into one bulky output file.
它正如其名:您可能不想将所有 JavaScript 打包到一个庞大的输出文件中。
It's a job webpack does for you to split off parts of your bundle which you only need on certain pages of your application.
webpack 为你做的一项工作是将你的 bundle 的一部分拆分出来,你只需要在应用程序的某些页面上使用这些部分。
Also, depending on how frequently you're working on your project's JavaScript, it might be a good idea to split off third party code from your bundle for caching purposes.
此外,根据您处理项目 JavaScript 的频率,将第三方代码从包中分离出来用于缓存可能是个好主意。
Read more: webpack Documentation – Code Splitting
阅读更多:webpack 文档 - 代码拆分
Caching
缓存
You may want to enhance your site's caching behaviour by adding a hash to your bundled file names which depends on their content. This will create (for example) a script.31aa1d3cad014475a618.js
instead of a scripts.js
.
您可能希望通过将散列添加到依赖于其内容的捆绑文件名来增强站点的缓存行为。这将创建(例如) ascript.31aa1d3cad014475a618.js
而不是 a scripts.js
。
That file can then be cached indefinitely because as soon as its contents change, the file name will change as well.
然后可以无限期地缓存该文件,因为一旦其内容更改,文件名也会更改。
Your PHP code might then use the webpack-manifest-plugin
to gain access to the generated file names.
然后,您的 PHP 代码可能会使用webpack-manifest-plugin
来访问生成的文件名。
Read more:
阅读更多:
- Immutable Cachingon how to cache your bundles forever
- webpack Documentation –
chunkhash
on how to enrich your bundle file names with hashes webpack-manifest-plugin
on how to generate amanifest.json
containing the file names of your current bundle
- 关于如何永远缓存你的包的不可变缓存
- webpack 文档——
chunkhash
关于如何用哈希来丰富你的包文件名 webpack-manifest-plugin
关于如何生成manifest.json
包含当前包的文件名的文件
Transpiling
转译
In case you want to use modern ES2015 code in your site's JavaScript (and are targeting non-evergreen browsers), you'll want to transpile them down to regular ES5. (If the term "ES2015" does not make any sense to you, you're most likely not using it and can ignore this paragraph.)
如果您想在站点的 JavaScript 中使用现代 ES2015 代码(并且针对非常绿浏览器),您需要将它们转换为常规 ES5。(如果“ES2015”这个词对你来说没有任何意义,你很可能没有使用它,可以忽略这一段。)
Read more: babel-loader
– A loader that runs Babel on your scripts
阅读更多:babel-loader
– 一个在你的脚本上运行 Babel 的加载器
CSS
CSS
There are webpack loaders for CSS. And Sass. And PostCSS. Whatever you need.
有用于 CSS 的 webpack 加载器。还有萨斯。和 PostCSS。无论你需要什么。
And since you're probably not planning to include your CSS via <script>
tags, get to know the Extract Text Pluginto generate actual .css
files.
由于您可能不打算通过<script>
标签包含您的 CSS ,因此请了解Extract Text Plugin以生成实际.css
文件。
Update:The Extract Text Pluginis very established. However, it's actually a kind of hack: It generates
.css
files even though webpack only knows JavaScript as its target language.However, this is no longer true as of webpack 4. There's now a system to define arbitrary module types, including CSS.
Long story short: Expect native CSS support in webpack to replace Extract Text Pluginsome time soon.
提示:路径更新:在提取文本插件是非常确定。然而,它实际上是一种 hack:
.css
即使 webpack 只知道 JavaScript 作为其目标语言,它也会生成文件。然而,从 webpack 4 开始,这不再正确。现在有一个系统可以定义任意模块类型,包括 CSS。
I'll mention this because this was a real pain point for me until I realized how webpack works here:
我会提到这一点,因为这对我来说是一个真正的痛点,直到我意识到 webpack 在这里是如何工作的:
Be aware that webpack will recognize your url(...)
statements and try to resolve them relative to your source files.
请注意,webpack 会识别您的url(...)
语句并尝试相对于您的源文件解析它们。
This means, your source file public/css/main.css
:
这意味着,您的源文件public/css/main.css
:
body {
background: url('../img/bg.jpg');
}
if your output path is public/dist/css/bundle.css
, will be transformed to:
如果您的输出路径为public/dist/css/bundle.css
,则将转换为:
body {
background: url('../../img/bg.jpg');
}
Read more:
阅读更多:
- style-loaderand css-loader– you'll hands down need those.
extract-text-webpack-plugin
Minifying
缩小
Update:Since webpack 4 was released in February 2018, this section is rather obsolete. Setting the new
mode
option to"production"
now automatically applies JavaScript minification.
更新:由于 webpack 4 于 2018 年 2 月发布,本节已经过时。将新
mode
选项设置为"production"
现在会自动应用 JavaScript 缩小。
There is a Terserplugin for webpack to minify your JavaScript. Minifying CSS is a feature already builtin to the css-loader
plugin mentioned above.
有一个用于 webpack的Terser插件来缩小你的 JavaScript。缩小 CSS 是上述css-loader
插件的内置功能。
Read more: Terser webpack Plugin
阅读更多:Terser webpack 插件
Image Optimization
图像优化
webpack is a bundler, not a task runner. Thus, image optimization is not a genuine webpack task. You'd probably be better off using an actual task runner or just defining some npm
scripts for this.
webpack 是一个打包器,而不是任务运行器。因此,图像优化不是真正的 webpack 任务。您最好使用实际的任务运行程序或npm
为此定义一些脚本。
This does not mean webpack is not capable of doing this. There are plugins for pretty much everything.
这并不意味着 webpack 无法做到这一点。几乎所有东西都有插件。
Read more:
阅读更多:
- imagemincan minify images pretty nicely on its own.
- imagemin-webpack-pluginwill integrate that process into your webpack build chain.
- imagemin可以自己很好地缩小图像。
- imagemin-webpack-plugin会将该过程集成到您的 webpack 构建链中。
Live Reloading
实时重装
Your problems with live reloading have a pretty simple cause: a webpack dev server is just a simple Node.js server serving only static files.
实时重新加载的问题有一个非常简单的原因:webpack 开发服务器只是一个简单的 Node.js 服务器,仅提供静态文件。
For you're case, webpack-dev-server
probably is the wrong tool at all. Try webpack-livereload-plugin
instead for a live reloader that you can just include via <script>
tag.
对于您的情况,webpack-dev-server
可能根本是错误的工具。尝试webpack-livereload-plugin
使用实时重新加载器,您可以通过<script>
标签包含它。
Read more: webpack-livereload-plugin
阅读更多: webpack-livereload-plugin
Source Maps
源地图
Update:As of webpack 4 (released in February 2018), source maps are automatically generated when the new
mode
option is set to"development"
.
更新:从 webpack 4(2018 年 2 月发布)开始,当新
mode
选项设置为"development"
.
By all means, use source maps. They'll make your work with bundles so much easier you'll want to cry.
无论如何,请使用源映射。它们将使您使用捆绑包的工作变得更加轻松,您会想哭。
Read more: webpack Documentation – Source Maps
阅读更多:webpack 文档 - 源地图
Edge Cases
边缘情况
Usually, all your existing scripts you'll process with webpack should be running just fine.
通常,您将使用 webpack 处理的所有现有脚本都应该运行良好。
The only exception that comes to my mind right now would be regarding global entities.
我现在想到的唯一例外是关于全球实体。
Look at the following code:
看下面的代码:
function myFunc () {
console.log('I exist!')
}
This code in a plain JavaScript file would make myFunc
available everywhere in your JS code. But since webpack bundle code is wrapped inside callback functions (and thus leaving the global scope), there won't be any access to that function anymore.
纯 JavaScript 文件中的这段代码将myFunc
在您的 JS 代码中随处可用。但是由于 webpack bundle 代码被包装在回调函数中(因此离开了全局作用域),将无法再访问该函数。
Third party libraries should not be a problem there, they usually assign their globals to the window
object directly, but if you've already written JS code in your project, you should be aware of that.
第三方库在那里应该不成问题,他们通常window
直接将全局变量分配给对象,但是如果您已经在项目中编写了 JS 代码,那么您应该意识到这一点。
Automate!
自动化!
You'll want to automate as much of your workflow as possible.
您将希望尽可能多地自动化您的工作流程。
Consider running npm run prod
via a git hook before pushing / after pulling.
考虑npm run prod
在推/拉之后通过 git hook运行。
Hope this helps.
希望这可以帮助。
回答by Delcon
Based on the existing vue-templates and and the answer from @Loilo I made a vue template you can install with vue-cli
. This template jumpstarts you for a vue application you can extend with or integrate in you existing environment.
基于现有的 vue-templates 和@Loilo 的回答,我制作了一个 vue 模板,您可以使用vue-cli
. 该模板为您提供了一个可以扩展或集成到现有环境中的 vue 应用程序。
npm install -g vue-cli
vue init delcon/webpack-simple my-project
cd my-project
npm install
devwatch:
开发观察:
This template has an additional run devwatch option that watches for filechanges instead of using the webpack-dev-server. This makes it usable for any existing webserver enviroment.
这个模板有一个额外的 run devwatch 选项,它监视文件更改而不是使用 webpack-dev-server。这使其可用于任何现有的网络服务器环境。
npm run devwatch
dev:
开发:
to run it with the default webpack-dev-server, remove <script src="http://localhost:35729/livereload.js"></script>
in index.html
:
使用默认的WebPack-dev的服务器上运行它,删除<script src="http://localhost:35729/livereload.js"></script>
在index.html
:
npm run dev
build:
建造:
to build your project for production:
为生产构建项目:
npm run build